Created
September 18, 2012 04:47
-
-
Save bcatcho/3741315 to your computer and use it in GitHub Desktop.
UDK Camera
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Camera: defines the Point of View of a player in world space. | |
* Copyright 1998-2012 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; | |
/** 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<Actor> 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<CameraModifier> 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<EmitterCameraLensEffectBase> 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<CameraModifier_CameraShake> 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<CameraAnimInst> ActiveAnims; | |
/** Array of anim instances that are not playing and available */ | |
var protected array<CameraAnimInst> 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<CameraModifier> 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<MAX_ACTIVE_CAMERA_ANIMS; ++Idx) | |
{ | |
AnimInstPool[Idx] = new(Self) class'CameraAnimInst'; | |
// add everything to the free list initially | |
FreeAnims[Idx] = AnimInstPool[Idx]; | |
} | |
// spawn the two temp CameraActors used for updating CameraAnims | |
AnimCameraActor = Spawn(class'DynamicCameraActor', self,,,,, TRUE); | |
} | |
event Destroyed() | |
{ | |
// clean up the temp camera actors | |
AnimCameraActor.Destroy(); | |
super.Destroyed(); | |
} | |
/** | |
* Apply modifiers on Camera. | |
* @param DeltaTime Time is seconds since last update | |
* @param OutPOV Point of View | |
*/ | |
native function ApplyCameraModifiers(float DeltaTime, out TPOV OutPOV); | |
/** | |
* Initialize Camera for associated PlayerController | |
* @param PC PlayerController attached to this Camera. | |
*/ | |
function InitializeFor(PlayerController PC) | |
{ | |
CameraCache.POV.FOV = DefaultFOV; | |
PCOwner = PC; | |
SetViewTarget(PC.ViewTarget); | |
// set the level default scale | |
SetDesiredColorScale(WorldInfo.DefaultColorScale, 5.f); | |
// Force camera update so it doesn't sit at (0,0,0) for a full tick. | |
// This can have side effects with streaming. | |
UpdateCamera(0.f); | |
} | |
/** | |
* returns camera's current FOV angle | |
*/ | |
function float GetFOVAngle() | |
{ | |
if( bLockedFOV ) | |
{ | |
return LockedFOV; | |
} | |
return CameraCache.POV.FOV; | |
} | |
/** | |
* Lock FOV to a specific value. | |
* A value of 0 to beyond 170 will unlock the FOV setting. | |
*/ | |
function SetFOV(float NewFOV) | |
{ | |
if( NewFOV < 1 || NewFOV > 170 ) | |
{ | |
bLockedFOV = FALSE; | |
return; | |
} | |
bLockedFOV = TRUE; | |
LockedFOV = NewFOV; | |
} | |
/** | |
* 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; | |
} | |
Loc += FreeCamOffset >> Rot; | |
Pos = Loc - Vector(Rot) * FreeCamDistance; | |
// @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); | |
Canvas.DrawText(" CamLoc:" $ CameraCache.POV.Location @ "CamRot:" $ CameraCache.POV.Rotation @ "FOV:" $ CameraCache.POV.FOV); | |
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<EmitterCameraLensEffectBase> 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<EmitterCameraLensEffectBase> 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); | |
LensEffect.UpdateLocation(CamLoc, CamRot, GetFOVAngle()); | |
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' | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment