1
0
KF2-Dev-Scripts/KFGame/Classes/KFSkeletalMeshComponent.uc
2020-12-13 18:01:13 +03:00

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
}