1
0
KF2-Dev-Scripts/Engine/Classes/DynamicSMActor.uc

298 lines
8.6 KiB
Ucode
Raw Permalink Normal View History

2020-12-13 15:01:13 +00:00
//=============================================================================
// DynamicSMActor.
// A non-static version of StaticMeshActor. This class is abstract, but used as a
// base class for things like KActor and InterpActor.
// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
//=============================================================================
class DynamicSMActor extends Actor
native
abstract;
var() const editconst StaticMeshComponent StaticMeshComponent;
var() const editconst DynamicLightEnvironmentComponent LightEnvironment;
/** Used to replicate mesh to clients */
var repnotify transient StaticMesh ReplicatedMesh;
/** used to replicate the materials in indices 0 and 1 */
var repnotify MaterialInterface ReplicatedMaterial0, ReplicatedMaterial1;
/** used to replicate StaticMeshComponent.bForceStaticDecals */
var repnotify bool bForceStaticDecals;
/** Extra component properties to replicate */
var repnotify vector ReplicatedMeshTranslation;
var repnotify rotator ReplicatedMeshRotation;
var repnotify vector ReplicatedMeshScale3D;
/** If a Pawn can be 'based' on this KActor. If not, they will 'bounce' off when they try to. */
var() bool bPawnCanBaseOn;
/** Pawn can base on this KActor if it is asleep -- Pawn will disable KActor physics while based */
var() bool bSafeBaseIfAsleep;
cpptext
{
/**
* Function that gets called from within Map_Check to allow this actor to check itself
* for any potential errors and register them with map check dialog.
*/
#if WITH_EDITOR
virtual void CheckForErrors();
#endif
protected:
#if USE_GAMEPLAY_PROFILER
/**
* This function actually does the work for the GetProfilerAssetObject and is virtual.
* It should only be called from GetProfilerAssetObject as GetProfilerAssetObject is safe to call on NULL object pointers
*/
virtual UObject* GetProfilerAssetObjectInternal() const;
#endif
/**
* This function actually does the work for the GetDetailInfo and is virtual.
* It should only be called from GetDetailedInfo as GetDetailedInfo is safe to call on NULL object pointers
*/
virtual FString GetDetailedInfoInternal() const;
}
replication
{
if (bNetDirty)
ReplicatedMesh, ReplicatedMaterial0, ReplicatedMaterial1, ReplicatedMeshTranslation, ReplicatedMeshRotation, ReplicatedMeshScale3D, bForceStaticDecals;
}
event PostBeginPlay()
{
Super.PostBeginPlay();
if( StaticMeshComponent != none )
{
ReplicatedMesh = StaticMeshComponent.StaticMesh;
bForceStaticDecals = StaticMeshComponent.bForceStaticDecals;
}
}
simulated event ReplicatedEvent(name VarName)
{
if (VarName == 'ReplicatedMesh')
{
if (ReplicatedMesh != StaticMeshComponent.StaticMesh)
{
// Enable the light environment if it is not already
LightEnvironment.bCastShadows = false;
LightEnvironment.SetEnabled(TRUE);
StaticMeshComponent.SetStaticMesh(ReplicatedMesh);
}
}
else if (VarName == nameof(ReplicatedMaterial0))
{
StaticMeshComponent.SetMaterial(0, ReplicatedMaterial0);
}
else if (VarName == nameof(ReplicatedMaterial1))
{
StaticMeshComponent.SetMaterial(1, ReplicatedMaterial1);
}
else if (VarName == 'ReplicatedMeshTranslation')
{
StaticMeshComponent.SetTranslation(ReplicatedMeshTranslation);
}
else if (VarName == 'ReplicatedMeshRotation')
{
StaticMeshComponent.SetRotation(ReplicatedMeshRotation);
}
else if (VarName == 'ReplicatedMeshScale3D')
{
StaticmeshComponent.SetScale3D(ReplicatedMeshScale3D / 100.0); // remove compensation for replication rounding
}
else if (VarName == nameof(bForceStaticDecals))
{
StaticMeshComponent.SetForceStaticDecals(bForceStaticDecals);
}
else
{
Super.ReplicatedEvent(VarName);
}
}
function OnSetMesh(SeqAct_SetMesh Action)
{
local bool bForce;
if( Action.MeshType == MeshType_StaticMesh )
{
bForce = Action.bIsAllowedToMove == StaticMeshComponent.bForceStaticDecals || Action.bAllowDecalsToReattach;
if( (Action.NewStaticMesh != None) &&
(Action.NewStaticMesh != StaticMeshComponent.StaticMesh || bForce) )
{
// Enable the light environment if it is not already
LightEnvironment.bCastShadows = false;
LightEnvironment.SetEnabled(TRUE);
// force decals on this mesh to be treated as movable or not (if False then decals will use fastpath)
bForceStaticDecals = !Action.bIsAllowedToMove;
StaticMeshComponent.SetForceStaticDecals(bForceStaticDecals);
// Don't allow decals to reattach since we are changing the static mesh
StaticMeshComponent.bAllowDecalAutomaticReAttach = Action.bAllowDecalsToReattach;
StaticMeshComponent.SetStaticMesh( Action.NewStaticMesh, Action.bAllowDecalsToReattach );
StaticMeshComponent.bAllowDecalAutomaticReAttach = true;
ReplicatedMesh = Action.NewStaticMesh;
ForceNetRelevant();
}
}
}
function OnSetMaterial(SeqAct_SetMaterial Action)
{
StaticMeshComponent.SetMaterial( Action.MaterialIndex, Action.NewMaterial );
if (Action.MaterialIndex == 0)
{
ReplicatedMaterial0 = Action.NewMaterial;
ForceNetRelevant();
}
else if (Action.MaterialIndex == 1)
{
ReplicatedMaterial1 = Action.NewMaterial;
ForceNetRelevant();
}
}
function SetStaticMesh(StaticMesh NewMesh, optional vector NewTranslation, optional rotator NewRotation, optional vector NewScale3D)
{
StaticMeshComponent.SetStaticMesh(NewMesh);
StaticMeshComponent.SetTranslation(NewTranslation);
StaticMeshComponent.SetRotation(NewRotation);
if (!IsZero(NewScale3D))
{
StaticMeshComponent.SetScale3D(NewScale3D);
ReplicatedMeshScale3D = NewScale3D * 100.0; // avoid rounding in replication code
}
ReplicatedMesh = NewMesh;
ReplicatedMeshTranslation = NewTranslation;
ReplicatedMeshRotation = NewRotation;
ForceNetRelevant();
}
/**
* Query to see if this DynamicSMActor can base the given Pawn
*/
simulated function bool CanBasePawn( Pawn P )
{
// Can base pawn if...
// Pawns can be based always OR
// Pawns can be based if physics is not awake
if( bPawnCanBaseOn ||
(bSafeBaseIfAsleep &&
StaticMeshComponent != None &&
!StaticMeshComponent.RigidBodyIsAwake()) )
{
return TRUE;
}
return FALSE;
}
/**
* If pawn is attached while asleep, turn off physics while pawn is on it
*/
event Attach( Actor Other )
{
local Pawn P;
super.Attach( Other );
if( bSafeBaseIfAsleep )
{
P = Pawn(Other);
if( P != None )
{
SetPhysics( PHYS_None );
}
}
}
/**
* If pawn is detached, turn back on physics (make sure no other pawns are based on it)
*/
event Detach( Actor Other )
{
local int Idx;
local Pawn P, Test;
local bool bResetPhysics;
super.Detach( Other );
P = Pawn(Other);
if( P != None )
{
bResetPhysics = TRUE;
for( Idx = 0; Idx < Attached.Length; Idx++ )
{
Test = Pawn(Attached[Idx]);
if( Test != None && Test != P )
{
bResetPhysics = FALSE;
break;
}
}
if( bResetPhysics )
{
SetPhysics( PHYS_RigidBody );
}
}
}
/**
* This will turn "off" the light environment so it will no longer update.
* This is useful for having a Timer call this once something has come to a stop and doesn't need 100% correct lighting.
**/
simulated final function SetLightEnvironmentToNotBeDynamic()
{
if( LightEnvironment != none )
{
LightEnvironment.bDynamic = FALSE;
}
}
defaultproperties
{
Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment
`if(`__TW_LIGHTING_MODIFICATIONS_)
bEnabled=False
`else
bEnabled=True
`endif
End Object
LightEnvironment=MyLightEnvironment
Components.Add(MyLightEnvironment)
Begin Object Class=StaticMeshComponent Name=StaticMeshComponent0
BlockRigidBody=false
LightEnvironment=MyLightEnvironment
bUsePrecomputedShadows=FALSE
End Object
CollisionComponent=StaticMeshComponent0
StaticMeshComponent=StaticMeshComponent0
Components.Add(StaticMeshComponent0)
bEdShouldSnap=true
bWorldGeometry=false
bGameRelevant=true
RemoteRole=ROLE_SimulatedProxy
bPathColliding=true
// DynamicSMActor do not have collision as a default. Having collision on them
// can be very slow (e.g. matinees where the matinee is controlling where
// the actors move and then they are trying to collide also!)
// The overall idea is that it is really easy to see when something doesn't
// collide correct and rectify it. On the other hand, it is hard to see
// something testing collision when it should not be while you wonder where
// your framerate went.
bCollideActors=false
bPawnCanBaseOn=true
// Automatically shadow parent to whatever this actor is attached to by default
bShadowParented=true
}