Ch08 Editor 2

11 분 소요

모듈

모듈구축

아래는 책대로 에디터용 모듈을 만드는 목적임.

참고하면 좋은 블로그

.UProject

	"Modules": [
		{
			"Name": "Example",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"AdditionalDependencies": [
				"Engine"
			]
		},
		{
			"Name": "ExampleEditor",
			"Type": "Editor",
			"LoadingPhase": "PostEngineInit",
			"AdditionalDependencies": [
				"Engine",
				"CoreUObject"
			]
		}
	]

json 으로 작성되었으며, “Modules” 객체에 모듈을 위처럼 추가하면 됨.

TypeEditor, Runtime 두개가 가능.

  • Runtime 모듈과 달리 Editor 모듈은 핫리로드가 지원이 안됨
  • IDE 에서 빌드 후 에디터 껏다 켜야함.

지금인 에디터에 추가할게 필요하므로 LoadingPhasePostEngineInit 이 됨.

.Target.cs

Visual Studio 에서 빌드할 모듈 이름을 여기에 등록함.

버전이 에디터와 게임 두개가 있으니까 편집툴만 할거면 뒤에 에디터 붙은거만 하면 되고, 게임에도 하는거면 에디터에도 해야함.

.Build.cs

  • PublicDependencyModuleNamesPrivateDependencyModuleNames
    • 전자는 모듈의 public header 파일에 의존되고 후자는 모듈의 private code 에 의존하는 파일이라 함.
    • 이는 모듈의 구성 폴더이름에 Public, Private, Classes 총 3가지 특별한 이름이 있는 것과 연관됨.
      • Source/[ModuleName]/[Public, Private, Classes]/... 이런구조.
      • Private 은 내부 모듈용으로 cpp 파일이 주로 들어감
      • Public 은 외부 모듈 공개용으로 h 파일이 주로 들어감
      • ClassesPublic 과 같지만 프로젝트에서 사용될 내용이 주로 들어감.

[ModuleName].h/cpp

  • IMPLEMENT_GAME_MODULE 은 새 모듈 클래스의 인스턴스를 반환하는 C 함수로 InitializeComponent 를 선언하는데 #define 으로 되어있음
  • 게임 메인 모듈은 IMPLEMENT_PRIMARY_GAME_MODULE 로 선언되어야하고 최소 하나이상이어야 함.
  • FDefaultGameModuleImpl 은 최소형태의 모듈 클래스임
  • 에디터에서 쓰려면 접두사 F 붙여서 위 클래스 상속하면 됨.

클래스

TCommand

  • UE Editor 는 TCommand 를 기반으로 되어 UI 와 작업간을 연결시킴
  • CRTP(Curiously Recurring Template Pattern) 을 활용하는 클래스로 컴파일 다형성을 생성하며 Slate UI 코드에서 사용됨
  • Singleton 으로 인스턴스를 위한 Get() 을 지원하며, static 메소드로 구현부를 만들 필요가 없음
  • RegisterCommands() 함수에서 FUICommandInfo 들을 생성함
    • UI_COMMAND 매크로를 통해 FUICommandInfo 인스턴스를 생성함
    • 이 매크로 사용중엔 LOCTEXT_NAMESPACE 가 정의되어 있어야함
    • 이때 적절한 UI 요소를 바인딩 할 수 있음
    • 4번째 파라미터론 Button, ToggleButton, RadioButton, Check 등이 있음
    • 5번째 파라미터론 입력 코드 또는 명령을 활성화하는데 필요한 키 조합

FUICommandList

  • MapAction() 함수에서 FUICommandInfo 와 실행할 함수를 바인딩 할 수 있음.
  • 아래 FExtender 에서 확장할 때 인자로 쓰임

FExtender

  • MenuBar, Menu, Toolbar 를 확장할 때 사용되며 각각 Add[]Extension 함수로 FExtender 생성
    • MenuBar 는 맨 위에 [파일, 편집, 창, 도움말] 얘고
    • Menu 는 MenuBar 의 버튼을 누르면 아래에 뜨는 애들임
    • Toolbar 는 저장, 컴파일, 마켓플레이스 등이 있는 Viewport 바로 위의 바.
  • AddToolBarExtension 으로 TCommand 를 추가함
    • 첫번째 인자로 확장지점을 필요로 함.
      • Edit -> Editor Preferences -> Miscellaneous -> Display UI Extension Points
      • 위 옵션을 켜고 에디터를 껏다키면 녹색 글자로 확장지점이 나옴.
    • 네번째 인자로 void (*func)(FToolBarBuilder*) 형식의 델리게이트
      • 실질적인 생성은 위에서 바인딩한 함수에서 진행됨
  • 자신이 생성한 FExtenderRemoveExtension 으로 모듈이 꺼질 때 등에 삭제해줘야함

FLevelEditorModule

FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
level_editor_module.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender);

위처럼 사용하며 FExtender 에서 추가가능한 3가지 종류별로 ExtensibilityManager 가 있음

잘쓰는 옵션

  • UI 의 표시 이름 ( 버튼 등)
    • FToolbarBuilder 등 builder 에서 AddTo 로 넣은 이름
  • 접혔을 때 이름
    • TCommandUI_COMMAND 의 첫번째 인자

Slate

UE4 Editor 와 UI Framework 를 위해 에픽에서 개발한 프레임워크

void ExSlate::MyButton_Clicked()
{
	TSharedRef<SWindow> custom_window = SNew(SWindow)
		.Title(FText::FromString(TEXT("Custom Window")))
		.ClientSize(FVector2D(800, 400)).SupportsMinimize(false).SupportsMinimize(false)
		[
			SNew(SVerticalBox)
			+SVerticalBox::Slot().HAlign(HAlign_Center).VAlign(VAlign_Center)
			[
				SNew(STextBlock).Text(FText::FromString(TEXT("Hello from Slate")))
			]
		];

	IMainFrameModule& main_frame_module = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame"));
	
	if (main_frame_module.GetParentWindow().IsValid())
	{
		FSlateApplication::Get().AddWindowAsNativeChild(custom_window, main_frame_module.GetParentWindow().ToSharedRef());
	}
	else {
		FSlateApplication::Get().AddWindow(custom_window);
	}
}
  • 모든 Slate 위젯은 TSharedRef<>, TSharedPtr<> 형태로 상호작용함

Create

  • SNew() 매크로는 요청된 위젯 클래스에 템플릿된 TSharedRef<> 를 리턴
  • SNew(STextBlock) => TSharedPtr<STextBlock>
  • Window -> Developer Tool -> Widget Reflector 에서 생성된 위젯의 부모자식관계를 확인가능

Chaining

  • .Property(value).Property(value) 등으로 옵션을 체이닝해서 쓸 수 있음
  • 옵션 설정 후 [] 를 대괄호처럼 써서 위젯 내부의 콘텐츠를 지정할 수 있음
  • SVerticalBox 의 경우 SVerticalBox::Slot() 으로 자기 내부에 넣을 슬롯을 생성할 수 있음.
    • 이후에 나오는 체인은 슬롯에 대한 것으로, 똑같이 옵션과 내부컨텐츠를 넣을 수 있음

댓글남기기