////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// /// Copyright 2017 (C) Bruno Xavier B. Leite ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "PooledActor.h" #include "OBJPool_Shared.h" #include "Runtime/Engine/Classes/Particles/ParticleSystemComponent.h" ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// APooledActor::APooledActor(const FObjectInitializer &OBJ) : Super(OBJ) { InitialLifeSpan = 0.f; LifeSpanPool = 0.f; // SharedPool = nullptr; OwningPool = nullptr; } void APooledActor::PostInitProperties() { Super::PostInitProperties(); } void APooledActor::BeginPlay() { Super::BeginPlay(); } void APooledActor::EndPlay(const EEndPlayReason::Type EndPlayReason) { OnPoolBeginPlay.Clear(); OnPoolEndPlay.Clear(); // Super::EndPlay(EndPlayReason); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void APooledActor::Initialize() { Spawned = false; // SetLifeSpan(0.f); SetActorHiddenInGame(true); SetActorTickEnabled(false); SetActorEnableCollision(false); // TInlineComponentArrayComponents; GetComponents(Components); // for (UActorComponent* C : Components) { const auto &PS = Cast(C); if (PS) {PS->DeactivateSystem();} // C->SetActive(false); C->SetComponentTickEnabled(false); // const auto &P = Cast(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(this)); } else if (SharedPool && SharedPool->IsValidLowLevelFast()) { SharedPool->ReturnActor(const_cast(this)); } } void APooledActor::SetLifeSpanPool(float InLifespan) { if (IsValid(this) && HasAuthority() ) { LifeSpanPool = InLifespan; // if (InLifespan>0.0001f) { GetWorldTimerManager().SetTimer(LifeSpanHandle,this,&APooledActor::ReturnToPool,InLifespan); } else {GetWorldTimerManager().ClearTimer(LifeSpanHandle);} } } float APooledActor::GetLifeSpanPool() const { const float CurrentLifespan = GetWorldTimerManager().GetTimerRemaining(LifeSpanHandle); return (CurrentLifespan!=-1.0f) ? CurrentLifespan : 0.0f; } UObjectPool* APooledActor::GetOwningPool() const { return OwningPool; } USharedObjectPool* APooledActor::GetSharedPool() const { return SharedPool; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void APooledActor::SpawnFromPool(const bool Reconstruct, const FPoolSpawnOptions &SpawnOptions, const FTransform &SpawnTransform) { if ((!OwningPool||!OwningPool->IsValidLowLevelFast())&&(!SharedPool||!SharedPool->IsValidLowLevelFast())) { UE_LOG(LogTemp,Warning,TEXT("{Pool}:: %s"),TEXT("Actor trying to spawn from Pool, but Owning Pool Component is invalid!")); return;} // Spawned = true; // // TInlineComponentArrayComponents; GetComponents(Components); // for (UActorComponent* C : Components) { const auto &P = Cast(C); if (P && !P->IsA(UParticleSystemComponent::StaticClass())) { P->SetCollisionEnabled((ECollisionEnabled::Type)SpawnOptions.CollisionType); P->SetComponentTickEnabled(SpawnOptions.ActorTickEnabled); P->SetSimulatePhysics(SpawnOptions.SimulatePhysics); P->SetVisibility(true,true); } } // if ((OwningPool && OwningPool->ReinitializeInstances)||(SharedPool && SharedPool->ReinitializeInstances)) { SetActorLocationAndRotation(SpawnTransform.GetLocation(),SpawnTransform.GetRotation(),false,nullptr,ETeleportType::ResetPhysics); SetActorEnableCollision(SpawnOptions.EnableCollision); SetActorTickEnabled(SpawnOptions.ActorTickEnabled); SetActorScale3D(SpawnTransform.GetScale3D()); } // // SetActorHiddenInGame(false); } void APooledActor::FinishSpawnFromPool(const bool Reconstruct, const FTransform &Transform) { FTransform FinalRootComponentTransform = (RootComponent ? RootComponent->GetComponentTransform() : Transform); FinalRootComponentTransform.GetLocation().DiagnosticCheckNaN(TEXT("APooledActor::FinishSpawning: FinalRootComponentTransform.GetLocation()")); FinalRootComponentTransform.GetRotation().DiagnosticCheckNaN(TEXT("APooledActor::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(); #endif } // if (LifeSpanPool>0.0001f) { GetWorldTimerManager().SetTimer(LifeSpanHandle,this,&APooledActor::ReturnToPool,LifeSpanPool); } // // TInlineComponentArrayComponents; GetComponents(Components); // for (UActorComponent* C : Components) { const auto &PS = Cast(C); if (PS) {PS->ActivateSystem(false);} // C->SetActive(true); C->SetComponentTickEnabled(true); } // // EVENT_OnPoolBeginPlay(); OnPoolBeginPlay.Broadcast(); // Spawned = true; } void APooledActor::ReturnToPool() { TInlineComponentArrayComponents; GetComponents(Components); // for (UActorComponent* C : Components) { const auto &PS = Cast(C); if (PS) {PS->DeactivateSystem();} // C->SetActive(false); C->SetComponentTickEnabled(false); // const auto &P = Cast(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(this)); // OnPoolEndPlay.Broadcast(); EVENT_OnPoolEndPlay(); } else if (SharedPool && SharedPool->IsValidLowLevelFast()) { if (SharedPool->ReinitializeInstances) { GetWorld()->GetTimerManager().ClearTimer(LifeSpanHandle); } SharedPool->ReturnActor(const_cast(this)); // OnPoolEndPlay.Broadcast(); EVENT_OnPoolEndPlay(); } else {Destroy(true,true);} // Spawned = false; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void APooledActor::EVENT_OnPoolBeginPlay_Implementation(){} void APooledActor::EVENT_OnPoolEndPlay_Implementation(){} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////