[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