티스토리 뷰

에셋의 복제가 아닌 에디터 상에 있는 물체의 복제를 진행한다.

 

언리얼에는 4가지 서브시스템이 있음.

UEngineSubsystem, UEditorSubsystem, UGameInstanceSubsystem, ULocalPlayerSubsystem

우리가 사용하는 건 UEditorSubsystem이 된다. 이 서브시스템 하위의 UEditorActorSubsystem을 사용한다.

이 서브시스템에서는 우리는 GetSelectedLevelActors() 와 GetAllLevelActors() 함수를 사용하게 된다.

이 함수들은 static이 아니기 때문에 액세스 하기 위해서는 서브 시스템을 확보해야한다.

 

#include "Subsystems/EditorActorSubsystem.h"

bool UQuickActorActionsWidget::GetEditorActorSubsystem()
{
	if (!EditorActorSubsystem)
	{
		EditorActorSubsystem = GEditor->GetEditorSubsystem<UEditorActorSubsystem>();
	}

	return EditorActorSubsystem != nullptr;
}

EditorActorSubsystem 라는 서브시스템은 GEditor 에 접근해서 UEditorActorSubsystem 에디터 서브시스템을 가져올 수 있다.

 

레벨 내부에서 비슷한 이름을 가진 모든 액터를 선택하기를 원함. 액터 이름을 사용. 기존에 사용하던 에셋 이름과는 다름. 이를 ActorLabel 이라고 부름. (액터이름). 그래서 액터를 선택하려면 GetName이 아니라 GetActorLabel 을 해야함.

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ActorBatchSelection")
	TEnumAsByte<ESearchCase::Type> SearchCase = ESearchCase::IgnoreCase;

위의 TEnumAsByte<ESearchCase::Type> 를 if(Actor->GetActorLabel().Contains(NameToSearch, SearchCase)) 안에 넣으면 대소문자들에 대한 검색도 활성화/비활성화 할 수 있게 된다.

 

비슷한 이름을 가진 액터들을 전부 선택하는 함수.

void UQuickActorActionsWidget::SelectAllActorWithSimilarName()
{
	if (!GetEditorActorSubsystem()) return;

	TArray<AActor*> SelectedActors = EditorActorSubsystem->GetSelectedLevelActors();
	uint32 SelectionCounter = 0;

	if (SelectedActors.Num() == 0)
	{
		DebugHeader::ShowNotifyInfo(TEXT("No Actor Selected."));
		return;
	}

	if (SelectedActors.Num() > 1)
	{
		DebugHeader::ShowNotifyInfo(TEXT("You can onlt Select one actor."));
		return;
	}

	FString SelectedActorName = SelectedActors[0]->GetActorLabel();
	const FString NameToSearch = SelectedActorName.LeftChop(4);

	TArray<AActor*> AllLevelActors = EditorActorSubsystem->GetAllLevelActors();

	for (auto Actor : AllLevelActors)
	{
		if (!Actor) continue;

		if (Actor->GetActorLabel().Contains(NameToSearch, SearchCase))
		{
			EditorActorSubsystem->SetActorSelectionState(Actor, true);
			SelectionCounter++;
		}
	}

	if (SelectionCounter > 0)
	{
		DebugHeader::ShowNotifyInfo(TEXT("Successfully selected ") + FString::FromInt(SelectionCounter)
		+ TEXT(" actors."));
	}
	else
	{
		DebugHeader::ShowNotifyInfo(TEXT("No Actor with similar name found."));

	}
}

위에서 언급한 GetActorLabel 을 이용하여 현재 엑터의 이름을 가져오고 (배치되는 물체들은 뒤에 숫자만 붙기 때문) 앞 부분을 가지고 비슷한 액터를 찾는다. 이름만 비슷하면 전부 찾는 것이므로 원하지 않는 물체를 선택할수도 있게됨.

그러나 이 부분은 일단 감안하고 넘어간다.

그러면 이렇게 하나의 물체를 클릭하고 버튼 (위젯 만드는 방법은 생략) 을 누르면 같은 이름의 액터들을 모두 선택하게 된다.

 

이제 물체 복제를 진행.

EditorActorSubsystem 에서 DuplicateActor를 사용한다. 만들어진 엑터를 가지고 x,y,z 방향으로의 확장을 골라서 복제가능하다.

코드가 어렵진않아서 코드를 올린다.

void UQuickActorActionsWidget::DuplicateActors()
{
	if (!GetEditorActorSubsystem()) return;

	TArray<AActor*> SelectedActors = EditorActorSubsystem->GetSelectedLevelActors();
	uint32 Counter = 0;

	if (SelectedActors.Num() == 0)
	{
		DebugHeader::ShowNotifyInfo(TEXT("No Actor Selected."));
		return;
	}

	if (NumberOfDuplicates <= 0 || OffsetDist == 0.f)
	{
		DebugHeader::ShowNotifyInfo(TEXT("Did not specift a number of duplications or an offset distance"));
		return;
	}

	for (auto SelectedActor : SelectedActors)
	{
		if (!SelectedActor) continue;

		for (int32 i = 0; i < NumberOfDuplicates; i++)
		{
			AActor* DuplicatedActor =
				EditorActorSubsystem->DuplicateActor(SelectedActor, SelectedActor->GetWorld());

			if (!DuplicatedActor) continue;

			const float DuplicationOffsetDist = (i + 1) * OffsetDist;

			switch (AxisForDuplication)
			{
			case E_DuplicationAxis::EDA_XAxis:
				DuplicatedActor->AddActorWorldOffset(FVector(DuplicationOffsetDist, 0.f, 0.f));
				break;

			case E_DuplicationAxis::EDA_YAxis:
				DuplicatedActor->AddActorWorldOffset(FVector(0.f, DuplicationOffsetDist, 0.f));
				break;

			case E_DuplicationAxis::EDA_ZAxis:
				DuplicatedActor->AddActorWorldOffset(FVector(0.f, 0.f, DuplicationOffsetDist));
				break;

			case E_DuplicationAxis::EDA_MAX:
				break;
			default:
				break;
			}

			EditorActorSubsystem->SetActorSelectionState(DuplicatedActor, true);
			Counter++;
		}
	
	}

	if (Counter > 0)
	{
		DebugHeader::ShowNotifyInfo(TEXT("Successfully Duplicated ") + FString::FromInt(Counter)
			+ TEXT(" actors."));

	}
}

그리고 복제 버튼을 누르면 복제된다. 위의 움짤은 Y 방향으로의 복제.

위의 사진은 z 방향으로의 복제가 이루어졌을 때 이다.

'Unreal > Custom Editor' 카테고리의 다른 글

[UE 5.1] Actor Randomize Transform  (0) 2023.10.30
[UE 5.1] Custom Material Tool - 2  (1) 2023.10.13
[UE 5.1] Custom Material Tool - 1  (0) 2023.10.11
[UE 5.1] Custom Icon  (0) 2023.09.20
[UE 5.1] Custom Slate Widget 04  (0) 2023.09.19
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함