void FHierarchicalLODUtilities::DestroyCluster(ALODActor* InActor)
{
	// Find if it has a parent ALODActor
	AActor* Actor = CastChecked<AActor>(InActor);
	UWorld* World = Actor->GetWorld();
	ALODActor* ParentLOD = GetParentLODActor(InActor);

	const FScopedTransaction Transaction(LOCTEXT("UndoAction_DeleteCluster", "Deleting a (invalid) Cluster"));
	Actor->Modify();
	World->Modify();
	if (ParentLOD != nullptr)
	{
		ParentLOD->Modify();
		ParentLOD->RemoveSubActor(Actor);
	}

	// Clean out sub actors and update their LODParent
	while (InActor->SubActors.Num())
	{
		AActor* SubActor = InActor->SubActors[0];
		SubActor->Modify();
		InActor->RemoveSubActor(SubActor);
	}

	// Also destroy the cluster's data
	DestroyClusterData(InActor);

	World->DestroyActor(InActor);

	if (ParentLOD != nullptr && !ParentLOD->HasValidSubActors())
	{
		DestroyCluster(ParentLOD);
	}
}
void UChildActorComponent::DestroyChildActor(const bool bRequiresRename)
{
	// If we own an Actor, kill it now
	if(ChildActor != nullptr && !GExitPurge)
	{
		// if still alive, destroy, otherwise just clear the pointer
		if (!ChildActor->IsPendingKillOrUnreachable())
		{
#if WITH_EDITOR
			if (CachedInstanceData)
			{
				delete CachedInstanceData;
				CachedInstanceData = nullptr;
			}
#else
			check(!CachedInstanceData);
#endif
			// If we're already tearing down we won't be needing this
			if (!HasAnyFlags(RF_BeginDestroyed))
			{
				CachedInstanceData = new FChildActorComponentInstanceData(this);
			}

			UWorld* World = ChildActor->GetWorld();
			// World may be nullptr during shutdown
			if(World != nullptr)
			{
				UClass* ChildClass = ChildActor->GetClass();

				// We would like to make certain that our name is not going to accidentally get taken from us while we're destroyed
				// so we increment ClassUnique beyond our index to be certain of it.  This is ... a bit hacky.
				ChildClass->ClassUnique = FMath::Max(ChildClass->ClassUnique, ChildActor->GetFName().GetNumber());

				if (bRequiresRename)
				{
					const FString ObjectBaseName = FString::Printf(TEXT("DESTROYED_%s_CHILDACTOR"), *ChildClass->GetName());
					const ERenameFlags RenameFlags = ((GetWorld()->IsGameWorld() || IsLoading()) ? REN_DoNotDirty | REN_ForceNoResetLoaders : REN_DoNotDirty);
					ChildActor->Rename(*MakeUniqueObjectName(ChildActor->GetOuter(), ChildClass, *ObjectBaseName).ToString(), nullptr, RenameFlags);
				}
				World->DestroyActor(ChildActor);
			}
		}

		ChildActor = nullptr;
	}
}
void FHierarchicalLODUtilities::DestroyLODActor(ALODActor* InActor)
{
	const FScopedTransaction Transaction(LOCTEXT("UndoAction_DeleteLODActor", "Delete LOD Actor"));
	UWorld* World = InActor->GetWorld();
	World->Modify();
	InActor->Modify();
	
	ALODActor* ParentActor = FHierarchicalLODUtilities::GetParentLODActor(InActor);

	FHierarchicalLODUtilities::DestroyCluster(InActor);
	World->DestroyActor(InActor);

	if (ParentActor && !ParentActor->HasValidSubActors())
	{
		ParentActor->Modify();
		FHierarchicalLODUtilities::DestroyLODActor(ParentActor);
	}
}
void AGameplayDebuggerPlayerManager::UpdateAuthReplicators()
{
	UWorld* World = GetWorld();
	for (int32 Idx = PlayerData.Num() - 1; Idx >= 0; Idx--)
	{
		FGameplayDebuggerPlayerData& TestData = PlayerData[Idx];

		if (!IsValid(TestData.Replicator) || !IsValid(TestData.Replicator->GetReplicationOwner()))
		{
			if (IsValid(TestData.Replicator))
			{
				World->DestroyActor(TestData.Replicator);
			}

			if (IsValid(TestData.Controller))
			{
				TestData.Controller->Cleanup();
			}

			PlayerData.RemoveAt(Idx, 1, false);
		}
	}

	for (FConstPlayerControllerIterator It = World->GetPlayerControllerIterator(); It; It++)
	{
		APlayerController* TestPC = *It;
		if (TestPC && !TestPC->IsA<ADebugCameraController>())
		{
			const bool bNeedsReplicator = (GetReplicator(*TestPC) == nullptr);
			if (bNeedsReplicator)
			{
				AGameplayDebuggerCategoryReplicator* Replicator = World->SpawnActorDeferred<AGameplayDebuggerCategoryReplicator>(AGameplayDebuggerCategoryReplicator::StaticClass(), FTransform::Identity);
				Replicator->SetReplicatorOwner(TestPC);
				Replicator->FinishSpawning(FTransform::Identity, true);
			}
		}
	}

	PrimaryActorTick.TickInterval = PlayerData.Num() ? 5.0f : 0.5f;
}
Example #5
0
SVisualLogger::~SVisualLogger()
{
	UWorld* World = NULL;
#if WITH_EDITOR
	FCategoryFiltersManager::Get().SavePresistentData();

	UEditorEngine *EEngine = Cast<UEditorEngine>(GEngine);
	if (GIsEditor && EEngine != NULL)
	{
		// lets use PlayWorld during PIE/Simulate and regular world from editor otherwise, to draw debug information
		World = EEngine->PlayWorld != NULL ? EEngine->PlayWorld : EEngine->GetEditorWorldContext().World();

	}
	else
#endif
	if (!GIsEditor)
	{
	World = GEngine->GetWorld();
	}

	if (World == NULL)
	{
		World = GWorld;
	}

	if (World)
	{
		for (TActorIterator<AVisualLoggerRenderingActor> It(World); It; ++It)
		{
			World->DestroyActor(*It);
		}
	}

	UDebugDrawService::Unregister(DrawOnCanvasDelegateHandle);
	VisualLoggerCanvasRenderer.Reset();

	FVisualLogger::Get().RemoveDevice(InternalDevice.Get());
	InternalDevice.Reset();
}
void UChildActorComponent::DestroyChildActor()
{
    // If we own an Actor, kill it now
    if(ChildActor != nullptr && !GExitPurge)
    {
        // if still alive, destroy, otherwise just clear the pointer
        if(!ChildActor->IsPendingKill())
        {
#if WITH_EDITOR
            if (CachedInstanceData)
            {
                delete CachedInstanceData;
            }
#else
            check(!CachedInstanceData);
#endif
            CachedInstanceData = new FChildActorComponentInstanceData(this);

            UWorld* World = ChildActor->GetWorld();
            // World may be nullptr during shutdown
            if(World != nullptr)
            {
                UClass* ChildClass = ChildActor->GetClass();

                // We would like to make certain that our name is not going to accidentally get taken from us while we're destroyed
                // so we increment ClassUnique beyond our index to be certain of it.  This is ... a bit hacky.
                ChildClass->ClassUnique = FMath::Max(ChildClass->ClassUnique, ChildActor->GetFName().GetNumber());

                const FString ObjectBaseName = FString::Printf(TEXT("DESTROYED_%s_CHILDACTOR"), *ChildClass->GetName());
                ChildActor->Rename(*MakeUniqueObjectName(ChildActor->GetOuter(), ChildClass, *ObjectBaseName).ToString(), nullptr, REN_DoNotDirty);
                World->DestroyActor(ChildActor);
            }
        }

        ChildActor = nullptr;
    }
}
void UChildActorComponent::DestroyChildActor()
{
	// If we own an Actor, kill it now unless we don't have authority on it, for that we rely on the server
	// If the level that the child actor is being removed then don't destory the child actor so re-adding it doesn't
	// need to create a new actor
	if (ChildActor && ChildActor->HasAuthority() && !GetOwner()->GetLevel()->bIsBeingRemoved)
	{
		if (!GExitPurge)
		{
			// if still alive, destroy, otherwise just clear the pointer
			if (!ChildActor->IsPendingKillOrUnreachable())
			{
#if WITH_EDITOR
				if (CachedInstanceData)
				{
					delete CachedInstanceData;
					CachedInstanceData = nullptr;
				}
#else
				check(!CachedInstanceData);
#endif
				// If we're already tearing down we won't be needing this
				if (!HasAnyFlags(RF_BeginDestroyed) && !IsUnreachable())
				{
					CachedInstanceData = new FChildActorComponentInstanceData(this);
				}

				UWorld* World = ChildActor->GetWorld();
				// World may be nullptr during shutdown
				if (World != nullptr)
				{
					UClass* ChildClass = ChildActor->GetClass();

					// We would like to make certain that our name is not going to accidentally get taken from us while we're destroyed
					// so we increment ClassUnique beyond our index to be certain of it.  This is ... a bit hacky.
					int32& ClassUnique = ChildActor->GetOutermost()->ClassUniqueNameIndexMap.FindOrAdd(ChildClass->GetFName());
					ClassUnique = FMath::Max(ClassUnique, ChildActor->GetFName().GetNumber());

					// If we are getting here due to garbage collection we can't rename, so we'll have to abandon this child actor name and pick up a new one
					if (!IsGarbageCollecting())
					{
						const FString ObjectBaseName = FString::Printf(TEXT("DESTROYED_%s_CHILDACTOR"), *ChildClass->GetName());
						const ERenameFlags RenameFlags = ((GetWorld()->IsGameWorld() || IsLoading()) ? REN_DoNotDirty | REN_ForceNoResetLoaders : REN_DoNotDirty);
						ChildActor->Rename(*MakeUniqueObjectName(ChildActor->GetOuter(), ChildClass, *ObjectBaseName).ToString(), nullptr, RenameFlags);
					}
					else
					{
						ChildActorName = NAME_None;
						if (CachedInstanceData)
						{
							CachedInstanceData->ChildActorName = NAME_None;
						}
					}
					World->DestroyActor(ChildActor);
				}
			}
		}

		ChildActor = nullptr;
	}
}
void FSequencerActorBindingManager::SpawnOrDestroyObjectsForInstance( TSharedRef<FMovieSceneInstance> MovieSceneInstance, const bool bDestroyAll )
{
	bool bAnyLevelActorsChanged = false;

	// Get the list of puppet objects for the movie scene
	TArray< TSharedRef<FPuppetActorInfo> >& PuppetObjects = InstanceToPuppetObjectsMap.FindOrAdd( MovieSceneInstance );

	UMovieScene* MovieScene = MovieSceneInstance->GetMovieScene();

	// Remove any puppet objects that we no longer need
	{
		for( auto PuppetObjectIndex = 0; PuppetObjectIndex < PuppetObjects.Num(); ++PuppetObjectIndex )
		{
			if( PuppetObjects[ PuppetObjectIndex ]->GetType() == EPuppetObjectType::Actor )
			{
				TSharedRef< FPuppetActorInfo > PuppetActorInfo = StaticCastSharedRef< FPuppetActorInfo >( PuppetObjects[ PuppetObjectIndex ] );

				// Figure out if we still need this puppet actor
				bool bShouldDestroyActor = true;
				if( !bDestroyAll )
				{
					for( auto SpawnableIndex = 0; SpawnableIndex < MovieScene->GetSpawnableCount(); ++SpawnableIndex )
					{
						auto& Spawnable = MovieScene->GetSpawnable( SpawnableIndex );
						if( Spawnable.GetGuid() == PuppetActorInfo->SpawnableGuid )
						{
							bShouldDestroyActor = false;
							break;
						}
					}
				}

				if( bShouldDestroyActor )
				{
					AActor* PuppetActor = PuppetActorInfo->PuppetActor.Get();
					if( PuppetActor != NULL )
					{
						UWorld* PuppetWorld = PuppetActor->GetWorld();
						if( ensure( PuppetWorld != NULL ) )
						{
							// Destroy this actor
							{
								// Ignored unless called while game is running
								const bool bNetForce = false;

								// We don't want to dirty the level for puppet actor changes
								const bool bShouldModifyLevel = false;

								if( !bAnyLevelActorsChanged )
								{
									DeselectAllPuppetObjects();
								}

								// Actor should never be selected in the editor at this point.  We took care of that up above.
								ensure( !PuppetActor->IsSelected() );

								const bool bWasDestroyed = PuppetWorld->DestroyActor( PuppetActor, bNetForce, bShouldModifyLevel );

								if( bWasDestroyed )
								{
									bAnyLevelActorsChanged = true;
									PuppetObjects.RemoveAt( PuppetObjectIndex-- );
								}
								else
								{
									// @todo sequencer: At least one puppet couldn't be cleaned up!
								}
							}
						}
					}
					else
					{
						// Actor is no longer valid (probably the world was destroyed)
					}
				}
			}
			else
			{
				check(0);	// Unhandled type
			}
		}
	}

	if( !bDestroyAll )
	{
		for( auto SpawnableIndex = 0; SpawnableIndex < MovieScene->GetSpawnableCount(); ++SpawnableIndex )
		{
			FMovieSceneSpawnable& Spawnable = MovieScene->GetSpawnable( SpawnableIndex );

			// Must have a valid world for us to be able to do this
			if( ActorWorld != NULL )
			{
				// Do we already have a puppet for this spawnable?
				bool bIsAlreadySpawned = false;
				for( auto PuppetIndex = 0; PuppetIndex < PuppetObjects.Num(); ++PuppetIndex )
				{
					auto& PuppetObject = PuppetObjects[ PuppetIndex ];
					if( PuppetObject->SpawnableGuid == Spawnable.GetGuid() )
					{
						bIsAlreadySpawned = true;
						break;
					}
				}

				if( !bIsAlreadySpawned )
				{
					UClass* GeneratedClass = Spawnable.GetClass();
					if ( GeneratedClass != NULL && GeneratedClass->IsChildOf(AActor::StaticClass()))
					{
						AActor* ActorCDO = CastChecked< AActor >( GeneratedClass->ClassDefaultObject );

						const FVector SpawnLocation = ActorCDO->GetRootComponent()->RelativeLocation;
						const FRotator SpawnRotation = ActorCDO->GetRootComponent()->RelativeRotation;

						// @todo sequencer: We should probably spawn these in a specific sub-level!
						// World->CurrentLevel = ???;

						const FName PuppetActorName = NAME_None;

						// Override the object flags so that RF_Transactional is not set.  Puppet actors are never transactional
						// @todo sequencer: These actors need to avoid any transaction history.  However, RF_Transactional can currently be set on objects on the fly!
						const EObjectFlags ObjectFlags = RF_Transient;		// NOTE: We are omitting RF_Transactional intentionally

						// @todo sequencer livecapture: Consider using SetPlayInEditorWorld() and RestoreEditorWorld() here instead
						
						// @todo sequencer actors: We need to make sure puppet objects aren't copied into PIE/SIE sessions!  They should be omitted from that duplication!

						// Spawn the puppet actor
						FActorSpawnParameters SpawnInfo;
						SpawnInfo.Name = PuppetActorName;
						SpawnInfo.ObjectFlags = ObjectFlags;
						AActor* NewActor = ActorWorld->SpawnActor( GeneratedClass, &SpawnLocation, &SpawnRotation, SpawnInfo );
				
						if( NewActor )
						{
							// @todo sequencer: We're naming the actor based off of the spawnable's name.  Is that really what we want?
							FActorLabelUtilities::SetActorLabelUnique(NewActor, Spawnable.GetName());

							// Actor was spawned OK!

							// Keep track of this actor
							TSharedRef< FPuppetActorInfo > NewPuppetInfo( new FPuppetActorInfo() );
							NewPuppetInfo->SpawnableGuid = Spawnable.GetGuid();
							NewPuppetInfo->PuppetActor = NewActor;
							PuppetObjects.Add( NewPuppetInfo );
						}
						else
						{
							// Actor failed to spawn
							// @todo sequencer: What should we do when this happens to one or more actors?
						}
					}
				}
			}
		}
	}
}