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

214 lines
10 KiB
Ucode

/**
* this class manages a pool of ParticleSystemComponents
* it is meant to be used for single shot effects spawned during gameplay
* to reduce object overhead that would otherwise be caused by spawning dozens of Emitters
*
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
*/
class EmitterPool extends Actor
native
transient
config(Game);
/** template to base pool components off of - should not be used for effects or attached to anything */
var protected ParticleSystemComponent PSCTemplate;
/** components currently in the pool */
var transient const array<ParticleSystemComponent> PoolComponents;
/** components currently active */
var transient array<ParticleSystemComponent> ActiveComponents;
// NVCHANGE_BEGIN: JCAO - Add surrogate emitter for flex
/** surrogate flex emitters */
var transient ParticleSystemComponent FlexSurrogateComponent;
// NVCHANGE_END: JCAO - Add surrogate emitter for flex
/** maximum allowed active components - if this is greater than 0 and is exceeded, the oldest active effect is taken */
var int MaxActiveEffects;
/** option to log out the names of all active effects when the pool overflows */
var globalconfig bool bLogPoolOverflow;
var globalconfig bool bLogPoolOverflowList;
/** list of components that should be relative to an Actor */
struct native EmitterBaseInfo
{
var ParticleSystemComponent PSC;
var Actor Base;
var vector RelativeLocation;
var rotator RelativeRotation;
var bool bInheritBaseScale;
};
var transient array<EmitterBaseInfo> RelativePSCs;
/**
* The amount of time to allow the SMC and MIC arrays to be beyond their ideals.
*/
var float SMC_MIC_ReductionTime;
var transient float SMC_MIC_CurrentReductionTime;
/**
* The ideal number of StaticMeshComponents and MaterialInstanceConstants.
* If their counts are greater than this for more than ReductionTime, then
* they will be chopped down to their respective settings.
*/
var int IdealStaticMeshComponents;
var int IdealMaterialInstanceConstants;
/** The free StaticMeshComponents used by emitters in this pool */
var private transient const array<StaticMeshComponent> FreeSMComponents;
/** The free MaterialInstanceConstants used by emitters in this pool */
var private transient const array<MaterialInstanceConstant> FreeMatInstConsts;
cpptext
{
virtual void TickSpecial(FLOAT DeltaTime);
}
/** set to each pool component's finished delegate to return it to the pool
* for custom lifetime PSCs, must be called manually when done with the component
*/
native function OnParticleSystemFinished(ParticleSystemComponent PSC);
/** Cleans up the pool components, removing any unused
*
* @param bClearActive If TRUE, clear active as well as inactive pool components
*/
native final function ClearPoolComponents(bool bClearActive = false);
/** internal - detaches the given PSC and returns it to the pool */
protected native final function ReturnToPool(ParticleSystemComponent PSC);
/** internal - moves the SMComponents from given PSC to the pool free list */
protected native final function FreeStaticMeshComponents(ParticleSystemComponent PSC);
/**
* internal - retrieves a SMComponent from the pool free list
*
* @param bCreateNewObject If TRUE, create an SMC w/ the pool as its outer
*
* @return StaticMeshComponent The SMC, NULL if none was available/created
*/
protected native final function StaticMeshComponent GetFreeStaticMeshComponent(bool bCreateNewObject = true);
/** internal - moves the MIConstants from given SMComponent to the pool free list */
protected native final function FreeMaterialInstanceConstants(StaticMeshComponent SMC);
/**
* internal - retrieves a MaterialInstanceConstant from the pool free list
*
* @param bCreateNewObject If TRUE, create an MIC w/ the pool as its outer
*
* @return MaterialInstanceConstant The MIC, NULL if none was available/created
*/
protected native final function MaterialInstanceConstant GetFreeMatInstConsts(bool bCreateNewObject = true);
/** internal - helper for spawning functions
* gets a component from the appropriate pool array (checks PerEmitterPools)
* includes creating a new one if necessary as well as taking one from the active list if the max number active has been exceeded
* @return the ParticleSystemComponent to use
*/
protected native final function ParticleSystemComponent GetPooledComponent(ParticleSystem EmitterTemplate, bool bAutoActivate);
/** plays the specified effect at the given location and rotation, taking a component from the pool or creating as necessary
* @note: the component is returned so the caller can perform any additional modifications (parameters, etc),
* but it shouldn't keep the reference around as the component will be returned to the pool as soon as the effect is complete
* @param EmitterTemplate - particle system to create
* @param SpawnLocation - location to place the effect in world space
* @param SpawnRotation (opt) - rotation to place the effect in world space
* @param AttachToActor (opt) - if specified, component will move along with this Actor
* @param InInstigator (opt) - if specified and the particle system is lit, the new component will only share particle light environments with other components with matching instigators
* @param MaxDLEPooledReuses (opt) - if specified, limits how many components can use the same particle light environment. This is effectively a tradeoff between performance and particle lighting update rate.
* @param bInheritScaleFromBase (opt) - if TRUE scale from the base actor will be applied
* @return the ParticleSystemComponent the effect will use
*/
native function ParticleSystemComponent SpawnEmitter(ParticleSystem EmitterTemplate, vector SpawnLocation, optional rotator SpawnRotation, optional Actor AttachToActor, optional Actor InInstigator, optional int MaxDLEPooledReuses, optional bool bInheritScaleFromBase);
/** spawns a particle system attached to a SkeletalMeshComponent instead of to another Actor or to nothing
* as with SpawnEmitter(), the caller should avoid persistent references to the returned component as it will
* get automatically reclaimed when the effect is complete
* @note: if the owning Actor is destroyed before the effect completes, the ParticleSystemComponent will end up
* being marked pending kill and therefore eventually destroyed as well. The pool handles this gracefully,
* although it's obviously suboptimal.
* @param EmitterTemplate - particle system to create
* @param Mesh - mesh component to attach to
* @param AttachPointName - bone or socket to attach to
* @param bAttachToSocket (opt) - whether AttachPointName is a socket or bone name
* @param RelativeLoc (opt) - offset from bone location to place the effect (not used when attaching to socket)
* @param RelativeRot (opt) - offset from bone rotation to place the effect (not used when attaching to socket)
* @return the ParticleSystemComponent the effect will use
*/
native function ParticleSystemComponent SpawnEmitterMeshAttachment( ParticleSystem EmitterTemplate,
SkeletalMeshComponent Mesh, name AttachPointName, optional bool bAttachToSocket,
optional vector RelativeLoc, optional rotator RelativeRot );
/** spawns a pooled component that has a custom lifetime (controlled by the caller)
* the caller is responsible for attaching/detaching the component
* as well as calling our OnParticleSystemFinished() function when it is done with the component
* the pool may take the component back early - if it does, it will trigger the component's OnSystemFinished delegate
* so the caller can guarantee that it will be triggered
* @param EmitterTemplate - particle system to create
* @param bSkipAutoActivate - if TRUE, do not autoactivate the component when retrieving it from the pool
* @return the ParticleSystemComponent to use
*/
native function ParticleSystemComponent SpawnEmitterCustomLifetime(ParticleSystem EmitterTemplate, optional bool bSkipAutoActivate);
// NVCHANGE_BEGIN: JCAO - Add surrogate emitter for flex
simulated function PostBeginPlay()
{
// not using defaultproperties solves two problems: Template having stale data in it from the last level/PIE session,
// and LODSettings array being cleared in PostLoad when running the editor.
local ParticleSystem FlexParticleTemplate;
local DynamicLightEnvironmentComponent FlexLightEnvironment;
local ParticleSystemComponent SurrogateComponentTemplate;
local LightingChannelContainer LightingChannels;
SurrogateComponentTemplate = new() class'ParticleSystemComponent';
SurrogateComponentTemplate.SecondsBeforeInactive=9999999999999;
SurrogateComponentTemplate.CastShadow=false;
SurrogateComponentTemplate.bUseAsOccluder=true;
// SPH fluid was rendered at first
SurrogateComponentTemplate.TranslucencySortPriority=0;
FlexParticleTemplate = new(SurrogateComponentTemplate) class'ParticleSystem';
FlexParticleTemplate.LODSettings.Add(1);
FlexParticleTemplate.LODSettings[0].bLit=true;
FlexParticleTemplate.LODDistances.Add(1);
FlexParticleTemplate.LODDistances[0] = 0;
FlexLightEnvironment = new(SurrogateComponentTemplate) SurrogateComponentTemplate.LightEnvironmentClass;
FlexLightEnvironment.SetEnabled(false);
SurrogateComponentTemplate.SetLightEnvironment(FlexLightEnvironment);
LightingChannels.Indoor = true;
LightingChannels.Outdoor = true;
LightingChannels.bInitialized = true;
SurrogateComponentTemplate.SetLightingChannels(LightingChannels);
FlexSurrogateComponent = new(self) class'ParticleSystemComponent'(SurrogateComponentTemplate);
FlexSurrogateComponent.SetTemplate(new(FlexSurrogateComponent) class'ParticleSystem'(FlexParticleTemplate));
AttachComponent(FlexSurrogateComponent);
Super.PostBeginPlay();
}
// NVCHANGE_END: JCAO - Add surrogate emitter for flex
defaultproperties
{
Begin Object Class=ParticleSystemComponent Name=ParticleSystemComponent0
AbsoluteTranslation=true
AbsoluteRotation=true
SecondsBeforeInactive=0.0
End Object
PSCTemplate=ParticleSystemComponent0
TickGroup=TG_DuringAsyncWork
SMC_MIC_ReductionTime=2.5
IdealStaticMeshComponents=250
IdealMaterialInstanceConstants=250
`if(`__TW_)
//MaxActiveEffects=200
`endif
}