들어가며
실버바인의 3가지 모듈 중 처음으로 알아볼 것은 LuaEditor입니다.
가장 간단하기도 하고 맨 처음 시작이 VM(Virtual Machine)을 만들고
사용하기 때문에 해당 모듈을 먼저 알아보겠습니다.
1. Build.cs
먼저 모듈의 Build.cs 파일을 살펴보겠습니다.
using System.IO;
using UnrealBuildTool;
namespace UnrealBuildTool.Rules
{
public class SilvervineUE4LuaEditor : ModuleRules
{
public SilvervineUE4LuaEditor(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PrivatePCHHeaderFile = "SilvervineUE4LuaEditorPCH.h";
PublicIncludePaths.AddRange(new string[]
{
});
PrivateIncludePaths.AddRange(new string[]
{
});
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine",
"InputCore",
"SlateCore",
"UnrealEd",
"SilvervineUE4Lua",
});
}
}
}
PCH를 사용중에 있습니다. 파일을 열어보면 아직 따로 헤더가 추가되진 않았고, 파일만 만들어져 있습니다.
SilvervineUE4Lua모듈을 필요로 합니다.📌 모듈을 만들고
UnrealBuildTool.Rules네임스페이스로 묶어주면, 명확하게 관리할 수 있고 UBT 가 인식하므로 해당 모듈의 빌드 설정을 올바르게 처리합니다.
2.LuaEditor.cpp
다음으로 LuaEditor.cpp를 살펴보겠습니다.
// SilvervineUE4Lua / devCAT studio
// Copyright 2016 - 2020. Nexon Korea Corporation. All rights reserved.
#include "CoreMinimal.h"
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"
#define LOCTEXT_NAMESPACE "SilvervineUE4LuaEditor"
class FSilvervineUE4LuaEditorModule : public IModuleInterface
{
// Begin IModuleInterface
virtual void StartupModule() override
{
}
virtual void ShutdownModule() override
{
}
// End IModuleInterface
};
IMPLEMENT_MODULE(FSilvervineUE4LuaEditorModule, SilvervineUE4LuaEditor)
#undef LOCTEXT_NAMESPACE
- 기본형은 헤더파일과 cpp 파일로 나누어져 있는데, 따로 헤더파일 없이 cpp 파일 하나에 작성되었습니다.
- 기본 파일 구조에서 따로 코드가 작성된 것 없으므로 넘어가도록 하겠습니다.
3.LuaVirtualMachineFactory
LuaVirtualMachineFactory.h 와 LuaVirtualMachineFactory.cpp 를 살펴보겠습니다. 먼저 헤더파일 입니다.
//
// USUE4LuaVirtualMachine을 uasset으로 만들어주는 클래스 입니다.
//
UCLASS()
class USUE4LuaVirtualMachineFactory : public UFactory
{
GENERATED_UCLASS_BODY()
public:
// Begin UFactory Interface
virtual bool ConfigureProperties() override;
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
// End UFactory Interface
private:
UPROPERTY()
UClass* SelectedClass = nullptr;
};
- 언리얼 엔진에서는 외부의 에셋을 사용하거나 자신만의 커스텀 에셋을 생성하기 위해서
UFactory를 지원합니다. - 해당 클래스에서는
ConfigureProperties,FactoryCreateNew2개의 함수를 오버라이드 하고 있습니다.
ConfigureProperties
Opens a dialog to configure the factory properties. Return false if user opted out of configuring properties
- 해당 함수의 설명을 보면 속성을 구성하기 위한 대화상자를 열고, 사용자가 선택하지 않으면 false를 반환합니다.
FactoryCreateNew
UFactory클래스는 파일을 생성하기 위한 두 가지 함수를 제공합니다.- 외부의 파일을 가져와서 에셋을 만들 경우는
FactoryCreateFile - 새 UObject를 구성하는 경우는
FactoryCreateNew - 여기서는
FactoryCreateNew를 사용했습니다.
다음으로 cpp 파일을 살펴보겠습니다.
// SilvervineUE4Lua / devCAT studio
// Copyright 2016 - 2020. Nexon Korea Corporation. All rights reserved.
#include "LuaVirtualMachineFactory.h"
#include "ClassViewerFilter.h"
#include "ClassViewerModule.h"
#include "Kismet2/SClassPickerDialog.h"
#include "Modules/ModuleManager.h"
#include "SilvervineUE4LuaVirtualMachine.h"
USUE4LuaVirtualMachineFactory::USUE4LuaVirtualMachineFactory(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
bCreateNew = true;
SupportedClass = USUE4LuaVirtualMachine::StaticClass();
}
bool USUE4LuaVirtualMachineFactory::ConfigureProperties()
{
SelectedClass = nullptr;
FClassViewerModule& ClassViewerModule = FModuleManager::LoadModuleChecked<FClassViewerModule>("ClassViewer");
FClassViewerInitializationOptions Options;
Options.Mode = EClassViewerMode::ClassPicker;
Options.DisplayMode = EClassViewerDisplayMode::ListView;
{
struct FFilter : IClassViewerFilter
{
virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef<FClassViewerFilterFuncs> InFilterFuncs) override
{
return InClass->IsChildOf(USUE4LuaVirtualMachine::StaticClass());
}
virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef<const IUnloadedBlueprintData> InUnloadedClassData, TSharedRef<FClassViewerFilterFuncs> InFilterFuncs) override
{
return InUnloadedClassData->IsChildOf(USUE4LuaVirtualMachine::StaticClass());
}
};
Options.ClassFilter = MakeShareable(new FFilter);
}
const FText TitleText = FText::FromString(TEXT("Pick Parent Class")); // #todo: localization
UClass* ChosenClass = NULL;
const bool bPressedOk = SClassPickerDialog::PickClass(TitleText, Options, ChosenClass, USUE4LuaVirtualMachine::StaticClass());
if (bPressedOk)
{
SelectedClass = ChosenClass;
}
return bPressedOk;
}
UObject* USUE4LuaVirtualMachineFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
return NewObject<USUE4LuaVirtualMachine>(InParent, SelectedClass, Name, Flags);
}
크게 세 부분으로 나눌 수 있을 것 같습니다. 생성자, ConfigureProperties, FactoryCreateNew
위를 참고하여 자세히 살펴보겠습니다.
생성자
USUE4LuaVirtualMachineFactory::USUE4LuaVirtualMachineFactory(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
bCreateNew = true;
SupportedClass = USUE4LuaVirtualMachine::StaticClass();
}
bCreateNew는CanCreateNew함수에 의해 호출되는데 현재Factory에서 새 객체를 처음부터 만들 경우 true입니다.SupportedClass는 현재 Factory 에서 생산하는 클래스를 나타냅니다. 여기는LuaVM클래스를 생산하고 있습니다.
ConfigureProperties
bool USUE4LuaVirtualMachineFactory::ConfigureProperties()
{
SelectedClass = nullptr;
FClassViewerModule& ClassViewerModule = FModuleManager::LoadModuleChecked<FClassViewerModule>("ClassViewer");
FClassViewerInitializationOptions Options;
Options.Mode = EClassViewerMode::ClassPicker;
Options.DisplayMode = EClassViewerDisplayMode::ListView;
{
struct FFilter : IClassViewerFilter
{
virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef<FClassViewerFilterFuncs> InFilterFuncs) override
{
return InClass->IsChildOf(USUE4LuaVirtualMachine::StaticClass());
}
virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef<const IUnloadedBlueprintData> InUnloadedClassData, TSharedRef<FClassViewerFilterFuncs> InFilterFuncs) override
{
return InUnloadedClassData->IsChildOf(USUE4LuaVirtualMachine::StaticClass());
}
};
Options.ClassFilter = MakeShareable(new FFilter);
}
const FText TitleText = FText::FromString(TEXT("Pick Parent Class")); // #todo: localization
UClass* ChosenClass = NULL;
const bool bPressedOk = SClassPickerDialog::PickClass(TitleText, Options, ChosenClass, USUE4LuaVirtualMachine::StaticClass());
if (bPressedOk)
{
SelectedClass = ChosenClass;
}
return bPressedOk;
}
- 모듈 매니저를 통해
ClassViewerModule을 로드합니다. - 이후 클래스 관련 옵션들을 설정해줍니다.
- ClassViewerFilter를 설정해줍니다. 이때 필터링하는 클래스는
LuaVM입니다. - 5.0 버전부터는
ClassFilter가 아닌ClassFilters배열을 통한 처리를 권장합니다. - 클래스 선택 다이얼로그를 띄우고 클래스를 선택합니다.
FactoryCreateNew
UObject* USUE4LuaVirtualMachineFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
return NewObject<USUE4LuaVirtualMachine>(InParent, SelectedClass, Name, Flags);
}
- 새로 생성된 LuaVM 을 반환합니다.
마무리
LuaEditor 모듈에서는 Lua 스크립트 처리에 필요한 uasset VM을 생성하는 코드가 작성되었습니다.
- UFactory로 UObject 생성하기
- 모듈매니저를 통해 ClassViewerModule를 불러오기
- 불러온 ClassViewrModule을 통해 VM 클래스(uasset) 생성하기
위의 3단계를 거쳐서 VM을 생성하는 것을 알 수 있었습니다.
다음에는 본격적인 SlivervineUE4Lua를 살펴보겠습니다. 감사합니다.
