[UE] Asset Editor Tool 1: Asset 복제 기능의 Editor 만들기
언리얼 에디터 내에서 Asset을 원하는 숫자만큼 한 번에 복제하는 툴 기능을 구현하였다. 만약 0이하의 숫자를 기입하는 경우, 경고 문구를 띄우고 복제가 진행되지 않는다. 해당 기능을 사용해서 좀 더 편리하게 언리얼 작업을 진행해보자.
목차
Asset 복제 기능의 Editor 만들기
Plugin 생성 후 .uplugin 설정 변경하기
SWManager.uplugin


Game에는 영향을 안 주고 Editor에서만 영향을 주므로 Runtime이 아닌 Editor로 설정.
Plugin Module이 로드되는 시점 PreDefault로 변경
QuickAssetAction 생성


QuickAssetAction.h
#pragma once #include "CoreMinimal.h" #include "AssetActionUtility.h" #include "QuickAssetAction.generated.h" UCLASS() class SWMANAGER_API UQuickAssetAction : public UAssetActionUtility { GENERATED_BODY() public: UFUNCTION(CallInEditor) void TestFunc(); };
QuickAssetAction.cpp
#include "AssetActions/QuickAssetAction.h" void UQuickAssetAction::TestFunc() { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 8.f, FColor::Cyan, TEXT("Working")); } }
SWManager.Build.cs 수정
SWManager.Build.cs
// Copyright Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; public class SWManager : ModuleRules { public SWManager(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; PublicIncludePaths.AddRange( new string[] { // ... add public include paths required here ... } ); PrivateIncludePaths.AddRange( new string[] { System.IO.Path.GetFullPath(Target.RelativeEnginePath) + "/Source/Editor/Blutility/Private" } ); PublicDependencyModuleNames.AddRange( new string[] { "Core", "Blutility" // ... add other public dependencies that you statically link with here ... } ); PrivateDependencyModuleNames.AddRange( new string[] { "CoreUObject", "Engine", "Slate", "SlateCore", // ... add private dependencies that you statically link with here ... } ); DynamicallyLoadedModuleNames.AddRange( new string[] { // ... add any modules that your module loads dynamically here ... } ); } }
PrivateIncludePaths.AddRange(
new string[] {
System.IO.Path.GetFullPath(Target.RelativeEnginePath) + "/Source/Editor/Blutility/Private"} );
PublicDependencyModuleNames.AddRange(
new string[]{
"Core", "Blutility"} );
- 위의 것들을 추가하여 AssetActionUtility 를사용할 수 있게 해주기
실행화면


2 - Asset 복제하기 기능 만들기
SWManager.Build.cs 수정
SWManager.Build.cs
// Copyright Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; public class SWManager : ModuleRules { public SWManager(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; PrivateIncludePaths.AddRange( new string[] { System.IO.Path.GetFullPath(Target.RelativeEnginePath) + "/Source/Editor/Blutility/Private" } ); PublicDependencyModuleNames.AddRange( new string[] { "Core", "Blutility", "EditorScriptingUtilities" // ... add other public dependencies that you statically link with here ... } ); PrivateDependencyModuleNames.AddRange( new string[] { "CoreUObject", "Engine", "Slate", "SlateCore", } ); } }
PublicDependencyModuleNames.AddRange
- "EditorScriptingUtilities" 를 추가하여 UEditorAssetLibrary 사용할 수 있게 해주기
- 이것을 추가함으로써 플러그인 내의 클래스들에서 #include "EditorUtilityLibrary.h", #include "EditorAssetLibrary.h"를 선언하고 그 기능들을 가져다가 쓸 수 있다.
QuickAssetAction 수정
QuickAssetAction.h
#pragma once #include "CoreMinimal.h" #include "AssetActionUtility.h" #include "QuickAssetAction.generated.h" /** 우클릭 AssetAction에 새로운 기능 추가하기 * */ UCLASS() class SWMANAGER_API UQuickAssetAction : public UAssetActionUtility { GENERATED_BODY() public: UFUNCTION(CallInEditor) void DuplicateAssets(int32 NumOfDuplicates); };
QuickAssetAction.cpp
#include "AssetActions/QuickAssetAction.h" #include "DebugHeader.h" #include "EditorUtilityLibrary.h" #include "EditorAssetLibrary.h" void UQuickAssetAction::DuplicateAssets(int32 NumOfDuplicates) // Asset 복제하기 { if (NumOfDuplicates <= 0) // 복사 개수가 0이하라면 { // 잘못됬다는 문구를 띄우고 리턴한다 Print(TEXT("Please enter a VALID number"), FColor::Red); return; } TArray<FAssetData> SelectedAssetsData = UEditorUtilityLibrary::GetSelectedAssetData(); uint32 Counter = 0; for (const FAssetData& SelectedAssetData : SelectedAssetsData) { for (int32 i = 0; i < NumOfDuplicates; i++) { // Asset 경로, 이름짓기, 복제될 Asset의 경로 const FString SourceAssetPath = SelectedAssetData.ObjectPath.ToString(); const FString NewDuplicatedAssetName = SelectedAssetData.AssetName.ToString() + TEXT("_") + FString::FromInt(i + 1); const FString NewPathName = FPaths::Combine(SelectedAssetData.PackagePath.ToString(), NewDuplicatedAssetName); // SourceAssetPath경로에 있는 Asset을 NewPathName경로로 복제 if (UEditorAssetLibrary::DuplicateAsset(SourceAssetPath, NewPathName)) { UEditorAssetLibrary::SaveAsset(NewPathName, false); // NewPathName경로에 Asset을 저장 ++Counter; } } } if (Counter > 0) // 복제가 0 초과면 문구 띄우기 { Print(TEXT("Successfully duplicated " + FString::FromInt(Counter) + " files"), FColor::Green); } }
실행화면


3. FMessageDialog 띄우기
FMessageDialog::Open()의 리턴타입은 EAppReturnType::Type
FMessageDialog 관련 내용들은 Runtime\Core\Misc\MessageDialog.h.cpp에 정의되어 있다.
FMessageDialog::Open()의 리턴타입은 EAppReturnType::Type 이다.

0미만의 숫자의 기입 했을때 MessageDialog 문구창 띄우기
QuickAssetAction.cpp
#include "AssetActions/QuickAssetAction.h" #include "DebugHeader.h" #include "EditorUtilityLibrary.h" #include "EditorAssetLibrary.h" #include "Misc/MessageDialog.h" void UQuickAssetAction::DuplicateAssets(int32 NumOfDuplicates) // Asset 복제하기 { if (NumOfDuplicates <= 0) // 복사 개수가 0이하라면 { // 잘못됬다는 문구를 띄우고 리턴한다 FText MsgTitle = FText::FromString(TEXT("Warning")); FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(TEXT("Please enter a VALID number")), &MsgTitle); return; } TArray<FAssetData> SelectedAssetsData = UEditorUtilityLibrary::GetSelectedAssetData(); uint32 Counter = 0; for (const FAssetData& SelectedAssetData : SelectedAssetsData) { for (int32 i = 0; i < NumOfDuplicates; i++) { // Asset 경로, 이름짓기, 복제될 Asset의 경로 const FString SourceAssetPath = SelectedAssetData.ObjectPath.ToString(); const FString NewDuplicatedAssetName = SelectedAssetData.AssetName.ToString() + TEXT("_") + FString::FromInt(i + 1); const FString NewPathName = FPaths::Combine(SelectedAssetData.PackagePath.ToString(), NewDuplicatedAssetName); // SourceAssetPath경로에 있는 Asset을 NewPathName경로로 복제 if (UEditorAssetLibrary::DuplicateAsset(SourceAssetPath, NewPathName)) { UEditorAssetLibrary::SaveAsset(NewPathName, false); // NewPathName경로에 Asset을 저장 ++Counter; } } } if (Counter > 0) // 복제가 0 초과면 문구 띄우기 { Print(TEXT("Successfully duplicated " + FString::FromInt(Counter) + " files"), FColor::Green); } }
void UQuickAssetAction::DuplicateAssets(int32 NumOfDuplicates)
- if (NumOfDuplicates <= 0) {
// 잘못됬다는 문구를 띄우고 리턴한다
FText MsgTitle = FText::FromString(TEXT("Warning"));
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(TEXT("Please enter a VALID number")), &MsgTitle);
return; }
실행화면

코드 수정: 위에서 작업한 부분을 DebugHeader.h로 옮기고 함수를 콜하는 방식
DebugHeader.h
#pragma once #include "Misc/MessageDialog.h" #include "Widgets/Notifications/SNotificationList.h" #include "Framework/Notifications/NotificationManager.h" void Print(const FString& Message, const FColor& Color) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 8.f, Color, Message); } } void PrintLog(const FString& Message) { UE_LOG(LogTemp, Warning, TEXT("%s"), *Message); } EAppReturnType::Type ShowMsgDialog(EAppMsgType::Type MsgType, const FString& Message, bool bShowMsgAsWarning = true) { if (bShowMsgAsWarning) { // Warning과 잘못됬다는 문구(Message)를 띄우고 리턴한다 FText MsgTitle = FText::FromString(TEXT("Warning")); return FMessageDialog::Open(MsgType, FText::FromString(Message), &MsgTitle); } else { // 문구(Message)를 띄우고 리턴한다 return FMessageDialog::Open(MsgType, FText::FromString(Message)); } } void ShowNotifyInfo(const FString& Message) { FNotificationInfo NotifyInfo(FText::FromString(Message)); NotifyInfo.bUseLargeFont = true; NotifyInfo.FadeOutDuration = 7.0f; // NotifyInfo 메시지를 7초 동안 띄운다 FSlateNotificationManager::Get().AddNotification(NotifyInfo); }
QuickAssetAction.cpp
#include "AssetActions/QuickAssetAction.h" #include "DebugHeader.h" #include "EditorUtilityLibrary.h" #include "EditorAssetLibrary.h" void UQuickAssetAction::DuplicateAssets(int32 NumOfDuplicates) // Asset 복제하기 { if (NumOfDuplicates <= 0) // 복사 개수가 0이하라면 { // DebugHeader.h에 만든 ShowMsgDialog함수를 콜해 아래의 문구를 띄운다. ShowMsgDialog(EAppMsgType::Ok, TEXT("Please enter a VALID number")); return; } TArray<FAssetData> SelectedAssetsData = UEditorUtilityLibrary::GetSelectedAssetData(); uint32 Counter = 0; for (const FAssetData& SelectedAssetData : SelectedAssetsData) { for (int32 i = 0; i < NumOfDuplicates; i++) { // Asset 경로, 이름짓기, 복제될 Asset의 경로 const FString SourceAssetPath = SelectedAssetData.ObjectPath.ToString(); const FString NewDuplicatedAssetName = SelectedAssetData.AssetName.ToString() + TEXT("_") + FString::FromInt(i + 1); const FString NewPathName = FPaths::Combine(SelectedAssetData.PackagePath.ToString(), NewDuplicatedAssetName); // SourceAssetPath경로에 있는 Asset을 NewPathName경로로 복제 if (UEditorAssetLibrary::DuplicateAsset(SourceAssetPath, NewPathName)) { UEditorAssetLibrary::SaveAsset(NewPathName, false); // NewPathName경로에 Asset을 저장 ++Counter; } } } if (Counter > 0) // 복제가 0 초과면 문구 띄우기 { // DebugHeader.h에 만든 ShowNotifyInfo함수를 콜해 언리얼에디터 우측 하단에 아래의 문구를 띄운다. ShowNotifyInfo(TEXT("Successfully duplicated " + FString::FromInt(Counter) + " files")); } }
DebugHeader.h에서
- EAppReturnType::Type ShowMsgDialog(EAppMsgType::Type MsgType, const FString& Message, bool bShowMsgAsWarning = true)
- void ShowNotifyInfo(const FString& Message)
함수를 콜하여 문구를 띄우는 방식으로 코드 수정.
실행화면




'⭐ Unreal Engine > UE Plugin - Custom Editor Tool' 카테고리의 다른 글
[UE] Slate UI 2: 제거 마법사 - 에셋 리스트 띄우기 (0) | 2023.12.01 |
---|---|
[UE] Slate UI 1: Tab 띄우기 (0) | 2023.12.01 |
[UE] ContentBrowser Menu: 사용하지 않는 에셋/빈 폴더 제거 (0) | 2023.11.25 |
[UE] Asset Editor Tool 3: 사용하지 않는 Asset만 제거하기 (0) | 2023.11.25 |
[UE] Asset Editor Tool 2: Asset 접두어 넣기 (0) | 2023.11.25 |
댓글
이 글 공유하기
다른 글
-
[UE] Slate UI 1: Tab 띄우기
[UE] Slate UI 1: Tab 띄우기
2023.12.01 -
[UE] ContentBrowser Menu: 사용하지 않는 에셋/빈 폴더 제거
[UE] ContentBrowser Menu: 사용하지 않는 에셋/빈 폴더 제거
2023.11.25 -
[UE] Asset Editor Tool 3: 사용하지 않는 Asset만 제거하기
[UE] Asset Editor Tool 3: 사용하지 않는 Asset만 제거하기
2023.11.25 -
[UE] Asset Editor Tool 2: Asset 접두어 넣기
[UE] Asset Editor Tool 2: Asset 접두어 넣기
2023.11.25
댓글을 사용할 수 없습니다.