code
This commit is contained in:
230
Plugins/ObjectPool/Source/OBJPool/Private/PooledPawn.cpp
Normal file
230
Plugins/ObjectPool/Source/OBJPool/Private/PooledPawn.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////
|
||||
/// Copyright 2017 (C) Bruno Xavier B. Leite
|
||||
//////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PooledPawn.h"
|
||||
#include "OBJPool_Shared.h"
|
||||
#include "Runtime/Engine/Classes/Particles/ParticleSystemComponent.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
APooledPawn::APooledPawn(const FObjectInitializer &OBJ) : Super(OBJ) {
|
||||
LifeSpanPool = 0.f;
|
||||
}
|
||||
|
||||
void APooledPawn::Initialize() {
|
||||
Spawned = false;
|
||||
//
|
||||
SetLifeSpan(0.f);
|
||||
SetActorHiddenInGame(true);
|
||||
SetActorTickEnabled(false);
|
||||
SetActorEnableCollision(false);
|
||||
//
|
||||
TInlineComponentArray<UActorComponent*>Components;
|
||||
GetComponents(Components);
|
||||
//
|
||||
for (UActorComponent* C : Components) {
|
||||
const auto &PS = Cast<UParticleSystemComponent>(C);
|
||||
if (PS) {PS->DeactivateSystem();}
|
||||
//
|
||||
C->SetActive(false);
|
||||
C->SetComponentTickEnabled(false);
|
||||
//
|
||||
const auto &P = Cast<UPrimitiveComponent>(C);
|
||||
if (P && !P->IsA(UParticleSystemComponent::StaticClass())) {
|
||||
P->SetPhysicsAngularVelocityInDegrees(FVector::ZeroVector);
|
||||
P->SetPhysicsLinearVelocity(FVector::ZeroVector);
|
||||
P->SetComponentTickEnabled(false);
|
||||
P->SetSimulatePhysics(false);
|
||||
P->SetVisibility(false,true);
|
||||
}
|
||||
}
|
||||
//
|
||||
if (OwningPool && OwningPool->IsValidLowLevelFast()) {
|
||||
OwningPool->ReturnActor(const_cast<APooledPawn*>(this));
|
||||
}
|
||||
}
|
||||
|
||||
void APooledPawn::SetLifeSpanPool(float InLifespan) {
|
||||
if (IsValid(this)) {
|
||||
LifeSpanPool = InLifespan;
|
||||
//
|
||||
if (InLifespan>0.0001f) {
|
||||
GetWorldTimerManager().SetTimer(LifeSpanHandle,this,&APooledPawn::ReturnToPool,InLifespan);
|
||||
} else {GetWorldTimerManager().ClearTimer(LifeSpanHandle);}
|
||||
}
|
||||
}
|
||||
|
||||
float APooledPawn::GetLifeSpanPool() const {
|
||||
const float CurrentLifespan = GetWorldTimerManager().GetTimerRemaining(LifeSpanHandle);
|
||||
return (CurrentLifespan!=-1.0f) ? CurrentLifespan : 0.0f;
|
||||
}
|
||||
|
||||
void APooledPawn::BeginPlay() {
|
||||
Super::BeginPlay();
|
||||
}
|
||||
|
||||
void APooledPawn::EndPlay(const EEndPlayReason::Type EndPlayReason) {
|
||||
OnPoolBeginPlay.Clear();
|
||||
OnPoolEndPlay.Clear();
|
||||
//
|
||||
Super::EndPlay(EndPlayReason);
|
||||
}
|
||||
|
||||
void APooledPawn::SpawnFromPool(const bool Reconstruct, const FPoolSpawnOptions &SpawnOptions, const FTransform &SpawnTransform) {
|
||||
if (!OwningPool||!OwningPool->IsValidLowLevelFast()) {
|
||||
UE_LOG(LogTemp,Warning,TEXT("{Pool}:: %s"),TEXT("Pawn trying to spawn from Pool, but Owning Pool Component is invalid!"));
|
||||
return;}
|
||||
//
|
||||
Spawned = true;
|
||||
//
|
||||
//
|
||||
TInlineComponentArray<UActorComponent*>Components;
|
||||
GetComponents(Components);
|
||||
//
|
||||
for (UActorComponent* C : Components) {
|
||||
const auto &P = Cast<UPrimitiveComponent>(C);
|
||||
if (P && !P->IsA(UParticleSystemComponent::StaticClass())) {
|
||||
P->SetComponentTickEnabled(SpawnOptions.ActorTickEnabled);
|
||||
P->SetSimulatePhysics(SpawnOptions.SimulatePhysics);
|
||||
P->SetVisibility(true,true);
|
||||
}
|
||||
}
|
||||
//
|
||||
if (OwningPool->ReinitializeInstances) {
|
||||
SetActorLocationAndRotation(SpawnTransform.GetLocation(),SpawnTransform.GetRotation(),false,nullptr,ETeleportType::TeleportPhysics);
|
||||
SetActorEnableCollision(SpawnOptions.EnableCollision);
|
||||
SetActorTickEnabled(SpawnOptions.ActorTickEnabled);
|
||||
SetActorScale3D(SpawnTransform.GetScale3D());
|
||||
//
|
||||
FinishSpawnFromPool(Reconstruct,SpawnTransform);
|
||||
if (!Spawned) {return;}
|
||||
//
|
||||
if (LifeSpanPool>0.0001f) {
|
||||
GetWorldTimerManager().SetTimer(LifeSpanHandle,this,&APooledPawn::ReturnToPool,LifeSpanPool);
|
||||
}
|
||||
}
|
||||
//
|
||||
SetActorHiddenInGame(false);
|
||||
}
|
||||
|
||||
void APooledPawn::FinishSpawnFromPool(const bool Reconstruct, const FTransform &Transform) {
|
||||
FTransform FinalRootComponentTransform = (RootComponent ? RootComponent->GetComponentTransform() : Transform);
|
||||
//
|
||||
FinalRootComponentTransform.GetLocation().DiagnosticCheckNaN(TEXT("APooledPawn::FinishSpawning: FinalRootComponentTransform.GetLocation()"));
|
||||
FinalRootComponentTransform.GetRotation().DiagnosticCheckNaN(TEXT("APooledPawn::FinishSpawning: FinalRootComponentTransform.GetRotation()"));
|
||||
//
|
||||
if (GetWorld()) {
|
||||
FVector AdjustedLocation; FRotator AdjustedRotation;
|
||||
switch (SpawnCollisionHandlingMethod) {
|
||||
case ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn:
|
||||
AdjustedLocation = GetActorLocation();
|
||||
AdjustedRotation = GetActorRotation();
|
||||
if (GetWorld()->FindTeleportSpot(this,AdjustedLocation,AdjustedRotation)) {
|
||||
SetActorLocationAndRotation(AdjustedLocation,AdjustedRotation,false,nullptr,ETeleportType::TeleportPhysics);
|
||||
} break;
|
||||
//
|
||||
case ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding:
|
||||
AdjustedLocation = GetActorLocation();
|
||||
AdjustedRotation = GetActorRotation();
|
||||
if (GetWorld()->FindTeleportSpot(this,AdjustedLocation,AdjustedRotation)) {
|
||||
SetActorLocationAndRotation(AdjustedLocation,AdjustedRotation,false,nullptr,ETeleportType::TeleportPhysics);
|
||||
} else {
|
||||
UE_LOG(LogTemp,Warning,TEXT("Spawn Actor from Pool: failed because of collision at the spawn location [%s] for [%s]"),*AdjustedLocation.ToString(),*GetClass()->GetName());
|
||||
Initialize();
|
||||
return;}
|
||||
break;
|
||||
//
|
||||
case ESpawnActorCollisionHandlingMethod::DontSpawnIfColliding:
|
||||
if (GetWorld()->EncroachingBlockingGeometry(this,GetActorLocation(),GetActorRotation())) {
|
||||
UE_LOG(LogTemp,Warning,TEXT("Spawn Actor from Pool: failed because of collision at the spawn location [%s] for [%s]"),*GetActorLocation().ToString(),*GetClass()->GetName());
|
||||
Initialize();
|
||||
return;}
|
||||
break;
|
||||
//
|
||||
case ESpawnActorCollisionHandlingMethod::Undefined:
|
||||
case ESpawnActorCollisionHandlingMethod::AlwaysSpawn:
|
||||
default: break;}}
|
||||
//
|
||||
if (Reconstruct) {
|
||||
#if WITH_EDITOR
|
||||
ResetPropertiesForConstruction();
|
||||
RerunConstructionScripts();
|
||||
Reset();
|
||||
#endif
|
||||
}
|
||||
//
|
||||
if (LifeSpanPool>0.0001f) {
|
||||
GetWorldTimerManager().SetTimer(LifeSpanHandle,this,&APooledPawn::ReturnToPool,LifeSpanPool);
|
||||
}
|
||||
//
|
||||
//
|
||||
TInlineComponentArray<UActorComponent*>Components;
|
||||
GetComponents(Components);
|
||||
//
|
||||
for (UActorComponent* C : Components) {
|
||||
const auto &PS = Cast<UParticleSystemComponent>(C);
|
||||
if (PS) {PS->ActivateSystem(false);}
|
||||
//
|
||||
C->SetActive(true);
|
||||
C->SetComponentTickEnabled(true);
|
||||
}
|
||||
//
|
||||
//
|
||||
EVENT_OnPoolBeginPlay();
|
||||
OnPoolBeginPlay.Broadcast();
|
||||
//
|
||||
Spawned = true;
|
||||
}
|
||||
|
||||
void APooledPawn::ReturnToPool() {
|
||||
Spawned = false;
|
||||
//
|
||||
TInlineComponentArray<UActorComponent*>Components;
|
||||
GetComponents(Components);
|
||||
//
|
||||
for (UActorComponent* C : Components) {
|
||||
const auto &PS = Cast<UParticleSystemComponent>(C);
|
||||
if (PS) {PS->DeactivateSystem();}
|
||||
//
|
||||
C->SetActive(false);
|
||||
C->SetComponentTickEnabled(false);
|
||||
//
|
||||
const auto &P = Cast<UPrimitiveComponent>(C);
|
||||
if (P && !P->IsA(UParticleSystemComponent::StaticClass())) {
|
||||
P->SetPhysicsAngularVelocityInDegrees(FVector::ZeroVector);
|
||||
P->SetPhysicsLinearVelocity(FVector::ZeroVector);
|
||||
P->SetComponentTickEnabled(false);
|
||||
P->SetSimulatePhysics(false);
|
||||
P->SetVisibility(false,true);
|
||||
}
|
||||
}
|
||||
//
|
||||
SetActorEnableCollision(false);
|
||||
SetActorHiddenInGame(true);
|
||||
SetActorTickEnabled(false);
|
||||
//
|
||||
if (OwningPool && OwningPool->IsValidLowLevelFast()) {
|
||||
if (OwningPool->ReinitializeInstances) {
|
||||
GetWorld()->GetTimerManager().ClearTimer(LifeSpanHandle);
|
||||
} OwningPool->ReturnActor(const_cast<APooledPawn*>(this));
|
||||
//
|
||||
OnPoolEndPlay.Broadcast();
|
||||
EVENT_OnPoolEndPlay();
|
||||
} else {Destroy();}
|
||||
}
|
||||
|
||||
UPawnPool* APooledPawn::GetOwningPool() const {
|
||||
return OwningPool;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void APooledPawn::EVENT_OnPoolBeginPlay_Implementation(){}
|
||||
void APooledPawn::EVENT_OnPoolEndPlay_Implementation(){}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
Reference in New Issue
Block a user