콘텐츠로 이동

UE 확장 편집기 메뉴

UE 편집기 메뉴를 확장하는 방법을 기록하세요.

Hook

Hook은 확장 메뉴의 앵커로 이해할 수 있으며, 우리는 Hook 앞이나 뒤에 새로 추가된 메뉴 명령을 설정할 수 있습니다. UE의 내장 편집기 메뉴 명령은 대부분 Hook이 포함되어 있습니다. UE5에서 '편집 - 편집기 기본 설정 - 일반 - 기타 - UI 확장 지점 표시'로 이동하여 모든 메뉴의 Hook을 표시할 수 있습니다.

모듈 의존성

프로젝트 .Build.cs 파일에 LevelEditor, Slate, SlateCore, EditorStyle, EditorWidgets, UnrealEd, ToolMenus 의 의존 모듈을 추가해야 합니다.

PrivateDependencyModuleNames.AddRange(
    new string[]
    {
        "Core",
        "Engine",
        "CoreUObject",
        "LevelEditor",
        "Slate",
        "SlateCore",
        "EditorStyle",
        "EditorWidgets",
        "UnrealEd",
        "ToolMenus",
    }
    );

메뉴 바에 추가하기

코드를 직접 작성하세요.

auto MenuExtender = MakeShared<FExtender>();

MenuExtender->AddMenuBarExtension(
    "Help", EExtensionHook::After,      // Create After Help
    nullptr,
    FMenuBarExtensionDelegate::CreateLambda([](FMenuBarBuilder& MenuBarBuilder)
    {
        MenuBarBuilder.AddPullDownMenu(
            TEXT("MenuTest"),       // Name
            TEXT("MenuTest"),       // Tips
            FNewMenuDelegate::CreateLambda([](FMenuBuilder& MenuBuilder)
            {
                // create sub menus
            }),
            TEXT("MenuText"));      // New Hook
    })
);
FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor").GetMenuExtensibilityManager()->AddExtender(MenuExtender);

해당 코드를 실행하면 '도움말' 뒤에 '메뉴 테스트'라는 메뉴가 추가되는 것을 확인할 수 있습니다.

추가 명령

MenuBuilder.AddMenuEntry 인터페이스를 사용하세요.

// Inside MenuTest Lambda
MenuBuilder.AddMenuEntry(
    FText::FromName("MenuTestAction"), FText::FromName("MenuTestAction"),
    FSlateIcon(), FUIAction(FExecuteAction::CreateLambda([]()
    {
        // do action
    })));

CreateLambda 함수 내에 위의 코드를 넣으면 메뉴 명령이 생성됩니다.

메뉴 섹션입니다.

MenuBuilder.BeginSectionMenuBuilder.EndSection를 사용하세요:

MenuBuilder.BeginSection(NAME_None, FText::FromName("MenuTestSection"));
// code to create action
MenuBuilder.EndSection();

구분자

MenuBuilder.AddMenuSeparator();

하위 메뉴

하위 메뉴는 메뉴 바와 비슷하며 람다 내에서 정의해야합니다.

MenuBuilder.AddSubMenu(
    FText::FromName("MenuTestSub"), 
    FText::FromName("MenuTestSub"), 
    FNewMenuDelegate::CreateLambda([](FMenuBuilder& MenuBuilder)
    {
        MenuBuilder.AddMenuEntry(
            FText::FromName("MenuTestSubAction"), FText::FromName("MenuTestSubAction"),
            FSlateIcon(), FUIAction(FExecuteAction::CreateLambda([]()
            {
                // do action
            })));
    }));

SlateUI 컴포넌트

UI 요소를 추가할 수도 있습니다:

MenuBuilder.AddWidget(
    SNew(SHorizontalBox)
        + SHorizontalBox::Slot()
        .AutoWidth()
        [
            SNew(SEditableTextBox)
            .MinDesiredWidth(50)
            .Text(FText::FromName("MenuTestWidget"))
        ]

        + SHorizontalBox::Slot()
        .AutoWidth()
        .Padding(5, 0, 0, 0)
        [
        SNew(SButton)
        .Text(FText::FromName("ExtendWidget"))
        .OnClicked(FOnClicked::CreateLambda([]()
        {
            // do action
            return FReply::Handled();
        }))
        ],
    FText::GetEmpty()
);

Slate UI에 관련된 내용은 여기에서 자세히 다루지 않겠습니다. 관심이 있다면 다른 글을 찾아보세요.

Hook를 늘리는 메뉴

'도구 - 프로그래밍' 메뉴에 명령을 추가하는 예를 들어보겠습니다.

MenuExtender->AddMenuExtension(
    "Programming", EExtensionHook::After,
    nullptr,
    FMenuExtensionDelegate::CreateLambda([](FMenuBuilder& MenuBuilder)
    {
        MenuBuilder.AddMenuEntry(
        FText::FromName("MenuTestAction"), FText::FromName("MenuTestAction"),
        FSlateIcon(), FUIAction(FExecuteAction::CreateLambda([]()
        {
            // do action
        })));
    })
);

같은 이치로 다른 메뉴 유형을 추가할 수 있습니다.

완전한 코드

void BuildTestMenu()
{
    auto MenuExtender = MakeShared<FExtender>();

    MenuExtender->AddMenuBarExtension(
        "Help", EExtensionHook::After,
        nullptr,
        FMenuBarExtensionDelegate::CreateLambda([](FMenuBarBuilder& MenuBarBuilder)
        {
            MenuBarBuilder.AddPullDownMenu(
                FText::FromName("MenuTest"),
                FText::FromName("MenuTest"),
                FNewMenuDelegate::CreateLambda([](FMenuBuilder& MenuBuilder)
                {
                    MenuBuilder.BeginSection(NAME_None, FText::FromName("MenuTestSection"));
                    MenuBuilder.AddMenuSeparator();
                    MenuBuilder.AddMenuEntry(
                        FText::FromName("MenuTestAction"), FText::FromName("MenuTestAction"),
                        FSlateIcon(), FUIAction(FExecuteAction::CreateLambda([]()
                        {
                            // do action
                        })));

                    MenuBuilder.AddSubMenu(
                        FText::FromName("MenuTestSubb"),
                        FText::FromName("MenuTestSubb"),
                        FNewMenuDelegate::CreateLambda([](FMenuBuilder& MenuBuilder)
                        {
                            MenuBuilder.AddMenuEntry(
                                FText::FromName("MenuTestSubAction"), FText::FromName("MenuTestSubAction"),
                                FSlateIcon(), FUIAction(FExecuteAction::CreateLambda([]()
                                {
                                    // do action
                                })));
                        }));
                    MenuBuilder.EndSection();

                    MenuBuilder.AddWidget(
                    SNew(SHorizontalBox)
                         + SHorizontalBox::Slot()
                         .AutoWidth()
                         [
                             SNew(SEditableTextBox)
                             .MinDesiredWidth(50)
                             .Text(FText::FromName("MenuTestWidget"))
                         ]
                         + SHorizontalBox::Slot()
                         .AutoWidth()
                         .Padding(5, 0, 0, 0)
                         [
                            SNew(SButton)
                            .Text(FText::FromName("ExtendWidget"))
                            .OnClicked(FOnClicked::CreateLambda([]()
                            {
                                // do action
                                return FReply::Handled();
                            }))
                         ],
                     FText::GetEmpty()
                    );
                }),
                "MenuTest");
        })
    );

    MenuExtender->AddMenuExtension(
        "Programming", EExtensionHook::After,
        nullptr,
        FMenuExtensionDelegate::CreateLambda([](FMenuBuilder& MenuBuilder)
        {
            MenuBuilder.AddMenuEntry(
            FText::FromName("MenuTestAction"), FText::FromName("MenuTestAction"),
            FSlateIcon(), FUIAction(FExecuteAction::CreateLambda([]()
            {
                // do action
            })));
        })
    );

    FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor").GetMenuExtensibilityManager()->AddExtender(MenuExtender);
}

Original: https://wiki.disenone.site/ko

This post is protected by CC BY-NC-SA 4.0 agreement, should be reproduced with attribution.

이 게시물은 ChatGPT를 사용하여 번역되었습니다. 피드백모든 빠짐없이 확인해주세요.