187 lines
6.1 KiB
Ucode
187 lines
6.1 KiB
Ucode
|
//=============================================================================
|
||
|
// KFSkeletalMeshComponent
|
||
|
//=============================================================================
|
||
|
// SMC with FOV settings
|
||
|
//=============================================================================
|
||
|
// Killing Floor 2
|
||
|
// Copyright (C) 2015 Tripwire Interactive LLC
|
||
|
// Based on UDKSkeletalMeshComponent Copyright 1998-2012 Epic Games, Inc.
|
||
|
// - Andrew "Strago" Ladenberger
|
||
|
//=============================================================================
|
||
|
|
||
|
class KFSkeletalMeshComponent extends SkeletalMeshComponent
|
||
|
native;
|
||
|
|
||
|
cpptext
|
||
|
{
|
||
|
/** Creates a FKFSkeletalMeshSceneProxy (defined in UTWeapon.cpp) */
|
||
|
virtual FPrimitiveSceneProxy* CreateSceneProxy() override;
|
||
|
|
||
|
/** Default tick. */
|
||
|
virtual void Tick(FLOAT DeltaTime) override;
|
||
|
|
||
|
/** The KFSkeletalMesh ticks during async as well as post async, performing different work. */
|
||
|
void TickPostAsync(FLOAT DeltaTime);
|
||
|
|
||
|
/** Overridden ProcessRootMotion so that we can defer root motion until post asycn work. */
|
||
|
virtual void ProcessRootMotion( FLOAT DeltaTime, FBoneAtom& ExtractedRootMotionDelta, INT& bHasRootMotion ) override;
|
||
|
|
||
|
#if __TW_HEADSCALE_
|
||
|
virtual float GetHeadBoneScale() override { return HeadBoneScale; }
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
/** This variable is set during async tick so that we have the cached value when we tick physics calls in the post tick. */
|
||
|
var BoneAtom CachedExtractedRootMotionDelta;
|
||
|
|
||
|
/** This variable is set during async tick so that we have the cached value when we tick physics calls in the post tick. */
|
||
|
var int bCachedHasRootMotion;
|
||
|
|
||
|
/** This variable is set during async tick so that we have the cached value when we tick physics calls in the post tick. */
|
||
|
var bool bNeedsProcessRootMotion;
|
||
|
|
||
|
/** This changes the FOV used for rendering the skeletal mesh component. A value of 0 means to use the default. */
|
||
|
var() const float FOV;
|
||
|
|
||
|
/** whether textures are currently forced loaded */
|
||
|
var bool bForceLoadTextures;
|
||
|
|
||
|
/** When this component is ticking in async time, we need to know if there is pending work that needs to be ticked in post async
|
||
|
* because we actually switch during ragdoll to post async and don't want to perform deferred tick work.
|
||
|
*/
|
||
|
var bool bPendingDeferredWork;
|
||
|
|
||
|
/** when to clear forced streaming */
|
||
|
var float ClearStreamingTime;
|
||
|
|
||
|
/**
|
||
|
* If > 0, ensure the DeltaTime does not go above this value.
|
||
|
* Useful when issuing tick notifies (e.g. Hitbox collision) is critical
|
||
|
*/
|
||
|
var() float MinTickTimeStep;
|
||
|
|
||
|
/** Scale to use when doing line traces against the head bone */
|
||
|
var() float HeadBoneScale;
|
||
|
|
||
|
/**
|
||
|
* Force streamed textures to be loaded. Used to get MIPS streamed in before weapon comes up
|
||
|
* @PARAM bForcePreload if true causes streamed textures to be force loaded, if false, clears force loading
|
||
|
*/
|
||
|
simulated event PreloadTextures(bool bForcePreload, float ClearTime)
|
||
|
{
|
||
|
local int idx;
|
||
|
|
||
|
bForceLoadTextures = bForcePreload;
|
||
|
ClearStreamingTime = ClearTime;
|
||
|
|
||
|
for (Idx = 0; Idx < Materials.Length; Idx++)
|
||
|
{
|
||
|
if (Materials[Idx] != None)
|
||
|
{
|
||
|
Materials[Idx].SetForceMipLevelsToBeResident(true, bForcePreload, -1.0f);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** changes the value of FOV */
|
||
|
native final function SetFOV(float NewFOV);
|
||
|
|
||
|
/**
|
||
|
* Called by AnimNotify_PlayParticleEffect
|
||
|
* Looks for a socket name first then bone name
|
||
|
*
|
||
|
* @param AnimNotifyData The AnimNotify_PlayParticleEffect which will have all of the various params on it
|
||
|
*/
|
||
|
event bool PlayParticleEffect( const AnimNotify_PlayParticleEffect AnimNotifyData )
|
||
|
{
|
||
|
local KFParticleSystemComponent PSC;
|
||
|
|
||
|
// Assign 1st person particles to match depth and FOV
|
||
|
// abridged version (only attached, non-extreme content) from Super()
|
||
|
if ( DepthPriorityGroup == SDPG_Foreground
|
||
|
&& AnimNotifyData.bAttach
|
||
|
&& !AnimNotifyData.bIsExtremeContent )
|
||
|
{
|
||
|
PSC = new(self) class'KFParticleSystemComponent'; // move this to the object pool once it can support attached to bone/socket and relative translation/rotation
|
||
|
PSC.SetTemplate( AnimNotifyData.PSTemplate );
|
||
|
PSC.SetDepthPriorityGroup(SDPG_Foreground);
|
||
|
PSC.SetFOV(FOV);
|
||
|
if (AnimNotifyData.bUsePostUpdateWorkTickGroup)
|
||
|
{
|
||
|
PSC.SetTickGroup(TG_PostUpdateWork);
|
||
|
}
|
||
|
|
||
|
if( AnimNotifyData.SocketName != '' )
|
||
|
{
|
||
|
//`log( "attaching AnimNotifyData.SocketName" );
|
||
|
AttachComponentToSocket( PSC, AnimNotifyData.SocketName );
|
||
|
}
|
||
|
else if( AnimNotifyData.BoneName != '' )
|
||
|
{
|
||
|
//`log( "attaching AnimNotifyData.BoneName" );
|
||
|
AttachComponent( PSC, AnimNotifyData.BoneName );
|
||
|
}
|
||
|
|
||
|
PSC.ActivateSystem(true);
|
||
|
PSC.OnSystemFinished = SkelMeshCompOnParticleSystemFinished;
|
||
|
|
||
|
// We use this to keep track of particle systems spawned by animations
|
||
|
if( PSC != none && Owner != none )
|
||
|
{
|
||
|
Owner.OnAnimNotifyParticleSystemSpawned( AnimNotifyData, PSC );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return Super.PlayParticleEffect(AnimNotifyData);
|
||
|
}
|
||
|
|
||
|
/** Returns the duration (in seconds) for a named AnimSequence. Returns 0.f if no animation. */
|
||
|
final function float GetAnimInterruptTime(Name AnimSeqName)
|
||
|
{
|
||
|
return GetAnimNotifyTime(AnimSeqName, class'KFAnimNotify_Interrupt');
|
||
|
}
|
||
|
|
||
|
/** Returns the duration (in seconds) for a named AnimSequence. Returns 0.f if no animation. */
|
||
|
final function float GetReloadAmmoTime(Name AnimSeqName)
|
||
|
{
|
||
|
return GetAnimNotifyTime(AnimSeqName, class'KFAnimNotify_ReloadAmmo');
|
||
|
}
|
||
|
|
||
|
/** Returns the duration (in seconds) for a named AnimSequence. Returns 0.f if no animation. */
|
||
|
final function float GetAnimNotifyTime(Name AnimSeqName, class<AnimNotify> NotifyClass)
|
||
|
{
|
||
|
local int i;
|
||
|
local AnimSequence AnimSeq;
|
||
|
|
||
|
AnimSeq = FindAnimSequence(AnimSeqName);
|
||
|
if( AnimSeq == None || AnimSeq.RateScale <= 0.f )
|
||
|
{
|
||
|
return 0.f;
|
||
|
}
|
||
|
|
||
|
for(i=0; i<AnimSeq.Notifies.length; i++)
|
||
|
{
|
||
|
if( AnimSeq.Notifies[i].Notify == none )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if(ClassIsChildOf(AnimSeq.Notifies[i].Notify.Class, NotifyClass))
|
||
|
{
|
||
|
return (AnimSeq.Notifies[i].Time / AnimSeq.RateScale);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// see SkeletalMeshComponent::GetAnimLength
|
||
|
return (AnimSeq.SequenceLength / AnimSeq.RateScale);
|
||
|
}
|
||
|
|
||
|
DefaultProperties
|
||
|
{
|
||
|
FOV=0.0
|
||
|
HeadBoneScale=1.0
|
||
|
}
|