/** * Camera: defines the Point of View of a player in world space. * Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. */ class Camera extends Actor notplaceable native(Camera) dependson(EngineBaseTypes) transient; /** PlayerController Owning this Camera Actor */ var PlayerController PCOwner; /** Camera Mode */ var Name CameraStyle; /** default FOV */ var float DefaultFOV; /** true if FOV is locked to a constant value*/ var bool bLockedFOV; /** value FOV is locked at */ var float LockedFOV; /** FOV that is not effected by checkerboard resolution */ var float UnmodifiedFOV; /** If we should insert black areas when rendering the scene to ensure an aspect ratio of ConstrainedAspectRatio */ var bool bConstrainAspectRatio; /** If bConstrainAspectRatio is true, add black regions to ensure aspect ratio is this. Ratio is horizontal/vertical. */ var float ConstrainedAspectRatio; /** Default aspect ratio */ var float DefaultAspectRatio; /** Off-axis yaw angle offset */ var float OffAxisYawAngle; /** Off-axis pitch angle offset */ var float OffAxisPitchAngle; /** If we should apply FadeColor/FadeAmount to the screen. */ var bool bEnableFading; /** Color to fade to. */ var color FadeColor; /** Amount of fading to apply. */ var float FadeAmount; /** Apply fading of audio alongside the video */ var bool bFadeAudio; /** Indicates if CamPostProcessSettings should be used when using this Camera to view through. */ var float CamOverridePostProcessAlpha; /** Post-process settings to use if bCamOverridePostProcess is TRUE. */ var PostProcessSettings CamPostProcessSettings; /** Rendering overrides that are active on this camera. */ var RenderingPerformanceOverrides RenderingOverrides; /** * Forces Temporal AA to be disabled when True. * This is useful for hiding reprojection artifacts while certain game specific translucent effects are active. */ var transient bool bForceDisableTemporalAA; /** Turn on scaling of color channels in final image using ColorScale property. */ var bool bEnableColorScaling; /** Allows control over scaling individual color channels in the final image. */ var vector ColorScale; /** Should interpolate color scale values */ var bool bEnableColorScaleInterp; /** Desired color scale which ColorScale will interpolate to */ var vector DesiredColorScale; /** Color scale value at start of interpolation */ var vector OriginalColorScale; /** Total time for color scale interpolation to complete */ var float ColorScaleInterpDuration; /** Time at which interpolation started */ var float ColorScaleInterpStartTime; /** The actors which the camera shouldn't see. Used to hide actors which the camera penetrates. */ //var array HiddenActors; /* Caching Camera, for optimization */ struct native TCameraCache { /** Cached Time Stamp */ var float TimeStamp; /** cached Point of View */ var TPOV POV; }; var TCameraCache CameraCache, LastFrameCameraCache; /** * View Target definition * A View Target is responsible for providing the Camera with an ideal Point of View (POV) */ struct native TViewTarget { /** Target Actor used to compute ideal POV */ var() Actor Target; /** Controller of Target (only for non Locally controlled Pawns) */ var() Controller Controller; /** Point of View */ var() TPOV POV; /** Aspect ratio */ var() float AspectRatio; /** PlayerReplicationInfo (used to follow same player through pawn transitions, etc., when spectating) */ var() PlayerReplicationInfo PRI; }; /** Current ViewTarget */ var TViewTarget ViewTarget; /** Pending view target for blending */ var TViewTarget PendingViewTarget; /** Time left when blending to pending view target */ var float BlendTimeToGo; enum EViewTargetBlendFunction { /** Camera does a simple linear interpolation. */ VTBlend_Linear, /** Camera has a slight ease in and ease out, but amount of ease cannot be tweaked. */ VTBlend_Cubic, /** Camera immediately accelerates, but smoothly decelerates into the target. Ease amount controlled by BlendExp. */ VTBlend_EaseIn, /** Camera smoothly accelerates, but does not decelerate into the target. Ease amount controlled by BlendExp. */ VTBlend_EaseOut, /** Camera smoothly accelerates and decelerates. Ease amount controlled by BlendExp. */ VTBlend_EaseInOut, }; /** A set of parameters to describe how to transition between viewtargets. */ struct native ViewTargetTransitionParams { /** Total duration of blend to pending view target. 0 means no blending. */ var() float BlendTime; /** Function to apply to the blend parameter */ var() EViewTargetBlendFunction BlendFunction; /** Exponent, used by certain blend functions to control the shape of the curve. */ var() float BlendExp; /** If TRUE, lock outgoing viewtarget to last frame's camera position for the remainder of the blend. * This is useful if you plan to teleport the viewtarget, but want to keep the camera motion smooth. */ var() bool bLockOutgoing; structdefaultproperties { BlendFunction=VTBlend_Cubic BlendExp=2.f bLockOutgoing=FALSE } // providing the constructor by hand here, because we pass this as an optional parameter // and when the parameter isn't there, the default contructor is called. structcpptext { FViewTargetTransitionParams() {} FViewTargetTransitionParams(EEventParm) : BlendTime(0.f), BlendFunction(VTBlend_Cubic), BlendExp(2.f), bLockOutgoing(FALSE) {} } }; var ViewTargetTransitionParams BlendParams; /** List of camera modifiers to apply during update of camera position/ rotation */ var Array ModifierList; /** Distance to place free camera from view target */ var float FreeCamDistance; /** Offset to Z free camera position */ var vector FreeCamOffset; /** camera fade management */ var vector2d FadeAlpha; var float FadeTime, FadeTimeRemaining; // "Lens" effects (e.g. blood, dirt on camera) /** CameraBlood emitter attached to this camera */ var protected transient array CameraLensEffects; ///////////////////// // Camera Modifiers ///////////////////// /** Camera modifier for cone-driven screen shakes */ var() editinline transient CameraModifier_CameraShake CameraShakeCamMod; /** Class to use when instantiating screenshake modifier object. Provided to support overrides. */ var() protected class CameraShakeCamModClass; enum ECameraAnimPlaySpace { /** This anim is applied in camera space */ CAPS_CameraLocal, /** This anim is applied in world space */ CAPS_World, /** This anim is applied in a user-specified space (defined by UserPlaySpaceMatrix) */ CAPS_UserDefined, }; //////////////////////// // CameraAnim support //////////////////////// const MAX_ACTIVE_CAMERA_ANIMS = 8; /** Pool of anim instance objects available with which to play camera animations */ var protected CameraAnimInst AnimInstPool[MAX_ACTIVE_CAMERA_ANIMS]; /** Array of anim instances that are currently playing and in-use */ var protected array ActiveAnims; /** Array of anim instances that are not playing and available */ var protected array FreeAnims; /** Internal. Receives the output of individual camera animations. */ var protected transient DynamicCameraActor AnimCameraActor; /** if true, server will use camera positions replicated from the client instead of calculating locally. */ var bool bUseClientSideCameraUpdates; /** If true, replicate the client side camera position but don't use it, and draw the positions on the server */ var bool bDebugClientSideCamera; /** if true, send a camera update to the server on next update */ var bool bShouldSendClientSideCameraUpdate; cpptext { protected: void InitTempCameraActor(class ACameraActor* CamActor, class UCameraAnim* AnimToInitFor) const; void ApplyAnimToCamera(class ACameraActor const* AnimatedCamActor, class UCameraAnimInst const* AnimInst, FTPOV& OutPOV); UCameraAnimInst* AllocCameraAnimInst(); void ReleaseCameraAnimInst(UCameraAnimInst* Inst); UCameraAnimInst* FindExistingCameraAnimInst(UCameraAnim const* Anim); public: virtual void ModifyPostProcessSettings(FPostProcessSettings& PPSettings) const; void AssignViewTarget(AActor* NewTarget, FTViewTarget& VT, struct FViewTargetTransitionParams TransitionParams=FViewTargetTransitionParams(EC_EventParm)); AActor* GetViewTarget(); virtual UBOOL PlayerControlled(); } /** * Internal. Creates and initializes a new camera modifier of the specified class, returns the object ref. */ protected function CameraModifier CreateCameraModifier(class ModifierClass) { local CameraModifier NewMod; NewMod = new(Outer) ModifierClass; NewMod.Init(); NewMod.AddCameraModifier(Self); return NewMod; } function PostBeginPlay() { local int Idx; super.PostBeginPlay(); // Setup camera modifiers if( (CameraShakeCamMod == None) && (CameraShakeCamModClass != None) ) { CameraShakeCamMod = CameraModifier_CameraShake(CreateCameraModifier(CameraShakeCamModClass)); } // create CameraAnimInsts in pool for (Idx=0; Idx 170 ) { bLockedFOV = FALSE; return; } bLockedFOV = TRUE; LockedFOV = NewFOV; } /** Checkerborad-free FOV */ function SetUnmodifiedFOV(float NewFOV) { UnmodifiedFOV = NewFOV; } `if(`__TW_) function float GetActualFOV() { return GetFOVAngle(); } `endif /** * Master function to retrieve Camera's actual view point. * do not call this directly, call PlayerController::GetPlayerViewPoint() instead. * * @param OutCamLoc Camera Location * @param OutCamRot Camera Rotation */ final function GetCameraViewPoint(out vector OutCamLoc, out rotator OutCamRot) { // @debug: find out which calls are being made before the camera has been ticked // and have therefore one frame of lag. /* if( CameraCache.TimeStamp != WorldInfo.TimeSeconds ) { `Log(WorldInfo.TimeSeconds @ GetFuncName() @ "one frame of lag"); ScriptTrace(); } */ OutCamLoc = CameraCache.POV.Location; OutCamRot = CameraCache.POV.Rotation; } final function rotator GetCameraRotation() { return CameraCache.POV.Rotation; } /** * Sets the new desired color scale and enables interpolation. */ simulated function SetDesiredColorScale(vector NewColorScale, float InterpTime) { // if color scaling is not enabled if (!bEnableColorScaling) { // set the default color scale bEnableColorScaling = TRUE; ColorScale.X = 1.f; ColorScale.Y = 1.f; ColorScale.Z = 1.f; } // Don't bother interpolating if we're already scaling at the desired color if( NewColorScale != ColorScale ) { // save the current as original OriginalColorScale = ColorScale; // set the new desired scale DesiredColorScale = NewColorScale; // set the interpolation duration/time ColorScaleInterpStartTime = WorldInfo.TimeSeconds; ColorScaleInterpDuration = InterpTime; // and enable color scale interpolation bEnableColorScaleInterp = TRUE; } } /** * Performs camera update. * Called once per frame after all actors have been ticked. * Non-local players replicate the POV if bUseClientSideCameraUpdates is true */ simulated event UpdateCamera(float DeltaTime) { if ( PCOwner.IsLocalPlayerController() || !bUseClientSideCameraUpdates || bDebugClientSideCamera ) { DoUpdateCamera(DeltaTime); if (WorldInfo.NetMode == NM_Client && bShouldSendClientSideCameraUpdate) { PCOwner.ServerUpdateCamera(CameraCache.POV.Location, (CameraCache.POV.Rotation.Pitch & 65535) + ((CameraCache.POV.Rotation.Yaw & 65535) << 16)); bShouldSendClientSideCameraUpdate = FALSE; } } } simulated function DoUpdateCamera(float DeltaTime) { local TPOV NewPOV; local float DurationPct, BlendPct; // update color scale interpolation if (bEnableColorScaleInterp) { BlendPct = FClamp(`TimeSince(ColorScaleInterpStartTime)/ColorScaleInterpDuration,0.f,1.f); ColorScale = VLerp(OriginalColorScale,DesiredColorScale,BlendPct); // if we've maxed if (BlendPct == 1.f) { // disable further interpolation bEnableColorScaleInterp = FALSE; } } // Reset aspect ratio and postprocess override associated with CameraActor. bConstrainAspectRatio = FALSE; CamOverridePostProcessAlpha = 0.f; // Don't update outgoing viewtarget during an interpolation when bLockOutgoing is set. if( PendingViewTarget.Target == None || !BlendParams.bLockOutgoing ) { // Update current view target CheckViewTarget(ViewTarget); UpdateViewTarget(ViewTarget, DeltaTime); } // our camera is now viewing there NewPOV = ViewTarget.POV; ConstrainedAspectRatio = ViewTarget.AspectRatio; // if we have a pending view target, perform transition from one to another. if( PendingViewTarget.Target != None ) { BlendTimeToGo -= DeltaTime; // Reset aspect ratio. The call to UpdateViewTarget() may turn this back on. bConstrainAspectRatio = FALSE; // Update pending view target CheckViewTarget(PendingViewTarget); UpdateViewTarget(PendingViewTarget, DeltaTime); // blend.... if( BlendTimeToGo > 0 ) { DurationPct = (BlendParams.BlendTime - BlendTimeToGo) / BlendParams.BlendTime; switch (BlendParams.BlendFunction) { case VTBlend_Linear: BlendPct = Lerp(0.f, 1.f, DurationPct); break; case VTBlend_Cubic: BlendPct = FCubicInterp(0.f, 0.f, 1.f, 0.f, DurationPct); break; case VTBlend_EaseIn: BlendPct = FInterpEaseIn(0.f, 1.f, DurationPct, BlendParams.BlendExp); break; case VTBlend_EaseOut: BlendPct = FInterpEaseOut(0.f, 1.f, DurationPct, BlendParams.BlendExp); break; case VTBlend_EaseInOut: BlendPct = FInterpEaseInOut(0.f, 1.f, DurationPct, BlendParams.BlendExp); break; } //BlendPct = FCubicInterp(0.f, class'DialogueManager'.default.OutTan, 1.f, class'DialogueManager'.default.InTan, 1.f - DurationPct); // Update pending view target blend NewPOV = BlendViewTargets(ViewTarget, PendingViewTarget, BlendPct); } else { // we're done blending, set new view target ViewTarget = PendingViewTarget; // clear pending view target PendingViewTarget.Target = None; PendingViewTarget.Controller = None; BlendTimeToGo = 0; // our camera is now viewing there NewPOV = PendingViewTarget.POV; } if( bConstrainAspectRatio ) { // NOTE: We don't interpolate aspect ratio since either the prior or pending view target's AspectRatio // may be the default value (1.3333) unless the view target has a camera actor set to override // the aspect ratio. We'll just use the pending view target's aspect. ConstrainedAspectRatio = PendingViewTarget.AspectRatio; } } // Cache results FillCameraCache(NewPOV); if (bEnableFading && FadeTimeRemaining > 0.0) { FadeTimeRemaining = FMax(FadeTimeRemaining - DeltaTime, 0.0); if (FadeTime > 0.0) { FadeAmount = FadeAlpha.X + ((1.f - FadeTimeRemaining/FadeTime) * (FadeAlpha.Y - FadeAlpha.X)); } if (bFadeAudio) { ApplyAudioFade(); if (FadeAmount == 0) { bFadeAudio = false; } } } } /** Apply audio fading */ native function ApplyAudioFade(); /** * Blend 2 viewtargets. * * @param A Source view target * @paramn B destination view target * @param Alpha Alpha, % of blend from A to B. */ final function TPOV BlendViewTargets(const out TViewTarget A,const out TViewTarget B, float Alpha) { local TPOV POV; POV.Location = VLerp(A.POV.Location, B.POV.Location, Alpha); POV.FOV = Lerp(A.POV.FOV, B.POV.FOV, Alpha); POV.Rotation = RLerp(A.POV.Rotation, B.POV.Rotation, Alpha, TRUE); return POV; } /** * Cache update results */ final function FillCameraCache(const out TPOV NewPOV) { // Backup last frame results. if( CameraCache.TimeStamp != WorldInfo.TimeSeconds ) { LastFrameCameraCache = CameraCache; } CameraCache.TimeStamp = WorldInfo.TimeSeconds; CameraCache.POV = NewPOV; } /** * Make sure ViewTarget is valid */ native function CheckViewTarget(out TViewTarget VT); /** * Query ViewTarget and outputs Point Of View. * * @param OutVT ViewTarget to use. * @param DeltaTime Delta Time since last camera update (in seconds). */ function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime) { local vector Loc, Pos, HitLocation, HitNormal; local rotator Rot; local Actor HitActor; local CameraActor CamActor; local bool bDoNotApplyModifiers; local TPOV OrigPOV; local Pawn TPawn; // Don't update outgoing viewtarget during an interpolation if( PendingViewTarget.Target != None && OutVT == ViewTarget && BlendParams.bLockOutgoing ) { return; } // store previous POV, in case we need it later OrigPOV = OutVT.POV; // Default FOV on viewtarget OutVT.POV.FOV = DefaultFOV; // Viewing through a camera actor. CamActor = CameraActor(OutVT.Target); if( CamActor != None ) { CamActor.GetCameraView(DeltaTime, OutVT.POV); // Grab aspect ratio from the CameraActor. bConstrainAspectRatio = bConstrainAspectRatio || CamActor.bConstrainAspectRatio; OutVT.AspectRatio = CamActor.AspectRatio; // See if the CameraActor wants to override the PostProcess settings used. CamOverridePostProcessAlpha = CamActor.CamOverridePostProcessAlpha; CamPostProcessSettings = CamActor.CamOverridePostProcess; } else { TPawn = Pawn(OutVT.Target); // Give Pawn Viewtarget a chance to dictate the camera position. // If Pawn doesn't override the camera view, then we proceed with our own defaults if( TPawn == None || !TPawn.CalcCamera(DeltaTime, OutVT.POV.Location, OutVT.POV.Rotation, OutVT.POV.FOV) ) { // don't apply modifiers when using these debug camera modes. bDoNotApplyModifiers = TRUE; switch( CameraStyle ) { case 'Fixed' : // do not update, keep previous camera position by restoring // saved POV, in case CalcCamera changes it but still returns false OutVT.POV = OrigPOV; break; case 'ThirdPerson' : // Simple third person view implementation case 'FreeCam' : case 'FreeCam_Default': Loc = OutVT.Target.Location; Rot = OutVT.Target.Rotation; // Take into account Mesh Translation so it takes into account the PostProcessing we do there. if ((TPawn != None) && (TPawn.Mesh != None)) { Loc += (TPawn.Mesh.Translation - TPawn.default.Mesh.Translation) >> OutVT.Target.Rotation; } //OutVT.Target.GetActorEyesViewPoint(Loc, Rot); if( CameraStyle == 'FreeCam' || CameraStyle == 'FreeCam_Default' ) { Rot = PCOwner.Rotation; } `if(`__TW_) if( OutVT.Target != PCOwner ) { Loc += FreeCamOffset >> Rot; Pos = Loc - Vector(Rot) * FreeCamDistance; } else { Pos = Loc; } `else Loc += FreeCamOffset >> Rot; Pos = Loc - Vector(Rot) * FreeCamDistance; `endif // @fixme, respect BlockingVolume.bBlockCamera=false HitActor = Trace(HitLocation, HitNormal, Pos, Loc, FALSE, vect(12,12,12)); OutVT.POV.Location = (HitActor == None) ? Pos : HitLocation; OutVT.POV.Rotation = Rot; break; case 'FirstPerson' : // Simple first person, view through viewtarget's 'eyes' default : OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation); // Take into account Mesh Translation so it takes into account the PostProcessing we do there. if ((TPawn != None) && (TPawn.Mesh != None)) { OutVT.POV.Location += (TPawn.Mesh.Translation - TPawn.default.Mesh.Translation) >> OutVT.Target.Rotation; } break; } } } if( !bDoNotApplyModifiers ) { // Apply camera modifiers at the end (view shakes for example) ApplyCameraModifiers(DeltaTime, OutVT.POV); } //`log( WorldInfo.TimeSeconds @ GetFuncName() @ OutVT.Target @ OutVT.POV.Location @ OutVT.POV.Rotation @ OutVT.POV.FOV ); } /** * Set a new ViewTarget with optional BlendTime */ native final function SetViewTarget(Actor NewViewTarget, optional ViewTargetTransitionParams TransitionParams); /** * Give each modifier a chance to change view rotation/deltarot */ function ProcessViewRotation(float DeltaTime, out rotator OutViewRotation, out Rotator OutDeltaRot) { local int ModifierIdx; for( ModifierIdx = 0; ModifierIdx < ModifierList.Length; ModifierIdx++ ) { if( ModifierList[ModifierIdx] != None ) { if( ModifierList[ModifierIdx].ProcessViewRotation(ViewTarget.Target, DeltaTime, OutViewRotation, OutDeltaRot) ) { break; } } } } /** * list important Camera variables on canvas. HUD will call DisplayDebug() on the current ViewTarget when * the ShowDebug exec is used * * @param HUD - HUD with canvas to draw on * @input out_YL - Height of the current font * @input out_YPos - Y position on Canvas. out_YPos += out_YL, gives position to draw text for next debug line. */ simulated function DisplayDebug(HUD HUD, out float out_YL, out float out_YPos) { local Vector EyesLoc; local Rotator EyesRot; local Canvas Canvas; Canvas = HUD.Canvas; Canvas.SetDrawColor(255,255,255); Canvas.DrawText(" Camera Style:" $ CameraStyle @ "main ViewTarget:" $ ViewTarget.Target); out_YPos += out_YL; Canvas.SetPos(4,out_YPos); `if(`__TW_) Canvas.DrawText(" CamLoc:" $ CameraCache.POV.Location @ "CamRot:" $ CameraCache.POV.Rotation @ "FOV:" $ GetFOVAngle()); `else Canvas.DrawText(" CamLoc:" $ CameraCache.POV.Location @ "CamRot:" $ CameraCache.POV.Rotation @ "FOV:" $ CameraCache.POV.FOV); `endif out_YPos += out_YL; Canvas.SetPos(4,out_YPos); Canvas.DrawText(" AspectRatio:" $ ConstrainedAspectRatio); out_YPos += out_YL; Canvas.SetPos(4,out_YPos); if( ViewTarget.Target != None ) { ViewTarget.Target.GetActorEyesViewPoint(EyesLoc, EyesRot); Canvas.DrawText(" EyesLoc:" $ EyesLoc @ "EyesRot:" $ EyesRot); out_YPos += out_YL; Canvas.SetPos(4,out_YPos); } } //////////////////////////////// // Camera Lens Effects //////////////////////////////// /** Finds the first instance of a lens effect of the given class, using linear search. */ function EmitterCameraLensEffectBase FindCameraLensEffect(class LensEffectEmitterClass) { local EmitterCameraLensEffectBase LensEffect; foreach CameraLensEffects(LensEffect) { if ( !LensEffect.bDeleteMe && ( (LensEffect.Class == LensEffectEmitterClass) || (LensEffect.EmittersToTreatAsSame.Find(LensEffectEmitterClass) != INDEX_NONE) || (LensEffectEmitterClass.default.EmittersToTreatAsSame.Find(LensEffect.Class) != INDEX_NONE ) ) ) { return LensEffect; } } return None; } /** * Initiates a camera lens effect of the given class on this camera. */ function AddCameraLensEffect(class LensEffectEmitterClass) { local vector CamLoc; local rotator CamRot; local EmitterCameraLensEffectBase LensEffect; if (LensEffectEmitterClass != None) { if (!LensEffectEmitterClass.default.bAllowMultipleInstances) { LensEffect = FindCameraLensEffect(LensEffectEmitterClass); if (LensEffect != None) { LensEffect.NotifyRetriggered(); } } if (LensEffect == None) { // spawn with viewtarget as the owner so bOnlyOwnerSee works as intended LensEffect = Spawn( LensEffectEmitterClass, PCOwner.GetViewTarget() ); if (LensEffect != None) { GetCameraViewPoint(CamLoc, CamRot); `if(`__TW_) LensEffect.UpdateLocation( CamLoc, CamRot, GetActualFOV() ); `else LensEffect.UpdateLocation(CamLoc, CamRot, GetFOVAngle()); `endif LensEffect.RegisterCamera(self); CameraLensEffects.AddItem(LensEffect); } } } } /** Removes this particular lens effect from the camera. */ function RemoveCameraLensEffect(EmitterCameraLensEffectBase Emitter) { CameraLensEffects.RemoveItem(Emitter); } /** Removes all Camera Lens Effects. */ function ClearCameraLensEffects() { local EmitterCameraLensEffectBase LensEffect; foreach CameraLensEffects(LensEffect) { LensEffect.Destroy(); } // empty the array. unnecessary, since destruction will call RemoveCameraLensEffect, // but this gets it done in one fell swoop. CameraLensEffects.length = 0; } /** ------------------------------------------------------------ * Camera Shakes * ------------------------------------------------------------ */ /** * Play a camera shake */ function PlayCameraShake(CameraShake Shake, float Scale, optional ECameraAnimPlaySpace PlaySpace=CAPS_CameraLocal, optional rotator UserPlaySpaceRot) { if (Shake != None) { CameraShakeCamMod.AddCameraShake(Shake, Scale, PlaySpace, UserPlaySpaceRot); } } /** Stop playing a camera shake. */ function StopCameraShake(CameraShake Shake) { if (Shake != None) { CameraShakeCamMod.RemoveCameraShake(Shake); } } /** Internal. Returns intensity scalar in the range [0..1] for a shake originating at Epicenter. */ static function float CalcRadialShakeScale(Camera Cam, vector Epicenter, float InnerRadius, float OuterRadius, float Falloff) { local Vector POVLoc; local float DistPct; // using camera location so stuff like spectator cameras get shakes applied sensibly as well // need to ensure server has reasonably accurate camera position POVLoc = Cam.Location; if (InnerRadius < OuterRadius) { DistPct = (VSize(Epicenter - POVLoc) - InnerRadius) / (OuterRadius - InnerRadius); DistPct = 1.f - FClamp(DistPct, 0.f, 1.f); return DistPct ** Falloff; } else { // ignore OuterRadius and do a cliff falloff at InnerRadius return (VSize(Epicenter - POVLoc) < InnerRadius) ? 1.f : 0.f; } } /** * Static. Plays an in-world camera shake that affects all nearby players, with distance-based attenuation. */ static function PlayWorldCameraShake(CameraShake Shake, Actor ShakeInstigator, vector Epicenter, float InnerRadius, float OuterRadius, float Falloff, bool bTryForceFeedback, optional bool bOrientShakeTowardsEpicenter ) { local PlayerController PC; local float ShakeScale; local Rotator CamRot; local vector CamLoc; if( ShakeInstigator != None ) { foreach ShakeInstigator.LocalPlayerControllers(class'PlayerController', PC) { if (PC.PlayerCamera != None) { ShakeScale = CalcRadialShakeScale(PC.PlayerCamera, Epicenter, InnerRadius, OuterRadius, Falloff); if (bOrientShakeTowardsEpicenter && PC.Pawn != None) { PC.PlayerCamera.GetCameraViewPoint(CamLoc, CamRot); PC.ClientPlayCameraShake(Shake, ShakeScale, bTryForceFeedback, CAPS_UserDefined, rotator(Epicenter - CamLoc)); } else { PC.ClientPlayCameraShake(Shake, ShakeScale, bTryForceFeedback); } } } } } function ClearAllCameraShakes() { CameraShakeCamMod.RemoveAllCameraShakes(); // StopAllCameraAnims(TRUE); } /** ------------------------------------------------------------ * CameraAnim support * ------------------------------------------------------------ */ /** Play the indicated CameraAnim on this camera. Returns the CameraAnim instance. */ simulated native function CameraAnimInst PlayCameraAnim(CameraAnim Anim, optional float Rate=1.f, optional float Scale=1.f, optional float BlendInTime, optional float BlendOutTime, optional bool bLoop, optional bool bRandomStartTime, optional float Duration, optional bool bSingleInstance); /** * Stop playing all instances of the indicated CameraAnim. * bImmediate: TRUE to stop it right now, FALSE to blend it out over BlendOutTime. */ simulated native function StopAllCameraAnims(optional bool bImmediate); /** * Stop playing all instances of the indicated CameraAnim. * bImmediate: TRUE to stop it right now, FALSE to blend it out over BlendOutTime. */ simulated native function StopAllCameraAnimsByType(CameraAnim Anim, optional bool bImmediate); /** * Stops the given CameraAnim instance from playing. The given pointer should be considered invalid after this. */ simulated native function StopCameraAnim(CameraAnimInst AnimInst, optional bool bImmediate); defaultproperties { DefaultFOV=90.f DefaultAspectRatio=AspectRatio4x3 bHidden=TRUE RemoteRole=ROLE_None FreeCamDistance=256.f bUseClientSideCameraUpdates=TRUE bDebugClientSideCamera=FALSE CameraShakeCamModClass=class'CameraModifier_CameraShake' }