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 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);
	}
}
ALODActor* FHierarchicalLODUtilities::CreateNewClusterFromActors(UWorld* InWorld, AWorldSettings* WorldSettings, const TArray<AActor*>& InActors, const int32 InLODLevel /*= 0*/)
{
	checkf(InWorld != nullptr, TEXT("Invalid world"));
	checkf(InActors.Num() > 0, TEXT("Zero number of sub actors"));
	checkf(WorldSettings != nullptr, TEXT("Invalid world settings"));
	checkf(WorldSettings->bEnableHierarchicalLODSystem, TEXT("Hierarchical LOD system is disabled"));

	const FScopedTransaction Transaction(LOCTEXT("UndoAction_CreateNewCluster", "Create new Cluster"));
	InWorld->Modify();

	// Create the cluster
	ALODActor* NewCluster = FHierarchicalLODUtilities::CreateNewClusterActor(InWorld, InLODLevel, WorldSettings);
	checkf(NewCluster != nullptr, TEXT("Failed to create a new cluster"));

	// Add InActors to new cluster
	for (AActor* Actor : InActors)
	{
		checkf(Actor != nullptr, TEXT("Invalid actor in InActors"));
		
		// Check if Actor is currently part of a different cluster
		ALODActor* ParentActor = FHierarchicalLODUtilities::GetParentLODActor(Actor);
		if (ParentActor != nullptr)
		{
			// If so remove it first
			ParentActor->Modify();
			ParentActor->RemoveSubActor(Actor);

			// If the parent cluster is now empty (invalid) destroy it
			if (!ParentActor->HasValidSubActors())
			{
				FHierarchicalLODUtilities::DestroyCluster(ParentActor);
			}
		}

		// Add actor to new cluster
		NewCluster->AddSubActor(Actor);
	}

	// Update sub actor LOD parents to populate 
	NewCluster->UpdateSubActorLODParents();

	return NewCluster;
}
const bool FHierarchicalLODUtilities::RemoveActorFromCluster(AActor* InActor)
{
	checkf(InActor != nullptr, TEXT("Invalid InActor"));
	
	bool bSucces = false;

	ALODActor* ParentActor = FHierarchicalLODUtilities::GetParentLODActor(InActor);
	if (ParentActor != nullptr)
	{
		const FScopedTransaction Transaction(LOCTEXT("UndoAction_RemoveActorFromCluster", "Remove Actor From Cluster"));
		ParentActor->Modify();
		InActor->Modify();

		bSucces = ParentActor->RemoveSubActor(InActor);

		if (!ParentActor->HasValidSubActors())
		{
			DestroyCluster(ParentActor);
		}
	}
	
	return bSucces;
}