从阅读一个小规模的插件源码开始学习Unreal插件写作。

源码地址:

TextAsset

主要功能就是在Unreal编辑器中创建一个TextAsset格式的文本文件,并提供对这个文本文件中的内容进行反转的功能。

代码结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TextAsset
|-Binaries
|-Docs
|-Intermediate
|-Resources
|-Source
| |-TextAsset
| | |-Private
| | |-Public
| |-TextAssetEditor
| | |-Private
| | | |-AssetTools
| | | |-Factories
| | | |-Shared
| | | |-Styles
| | | |-Toolkits
| | | |-Widgets
|-TextAsset.uplugin
TextAsset.png
TextAsset.png

描述符文件TextAsset.uplugin:

前面的内容都是一些插件的基本属性,包括版本,引擎版本,开发者等等;最后一个Modules字段定义了两个模块:一个是运行时加载(Runtime)的TextAsset模块,一个是编辑器模块(Editor)TextAssetEditor。

TextAsset:

  • TextAssetModule重写了IModuleInterface接口的方法,实现了SupportsDynamicReloading 方法,这个方法返回 true,允许模块即时卸载。
  • UTextAsset中使用一个 FText 类型的变量:Text 用来将输入的字符串作为资源存储。

TextAssetEditor:

  • TextAssetEditorModule.cpp:定义了FTextAssetEditorModule类,这个类实现了IHasMenuExtensibility(表示类具有可扩展的默认菜单)、IHasToolBarExtensibility(表示类具有可扩展的默认工具栏)、IModuleInterface(所有模块实现应该派生自的接口类)等接口。

    对IModuleInterface 接口的实现主要是 StartupModule 与 ShutdownModule 两个函数,在 StartupModule 中,先对插件的样式进行了赋值,然后对 AssetTool 进行了注册,对菜单栏进行了注册,同时进行了设置;当然,在 ShutdownModule 中就进行了取消注册的函数。

    RegisterSettings 具体负责?

  • TextAssetAction.cpp:这个类继承自FAssetTypeActions_Base类,实现了若干关于Asset的函数,主要有:

    • GetActions:这里在AddMenuEntry中添加了资源可以执行的操作和这个操作相关的说明

      企业微信截图_156741384822.png

      对应着引擎中的:

      企业微信截图_15674139539249.png

      FUIAction对应了一些UI操作,详见:https://docs.unrealengine.com/en-US/API/Runtime/Slate/Framework/Commands/FUIAction/index.html

      总而言之,这里使用两个委托函数定义了激活此操作时执行的委托与在确定此操作是否可以执行时执行的委托,Reverse的具体实现其实就是双指针法,不做赘述;PostEditChange内部调用了 PostEditChangeProperty,这个函数在外部修改此对象上的属性时调用,用于传递编辑前和编辑后更改事件的结构;最后调用MarkPackageDirty用来将修改过但未保存的资源进行标记。

    • OpenAssetEditor:这个函数用来设置编辑器的布局,包括独立编辑的程序和以世界为中心的资产编辑器,两种布局根据EditWithinLevelEditor是否可用来决定。

  • TextAssetFactory.cpp

    这个类继承自UFactory类,负责通过从文件名导入新对象来创建新对象,在这个类的具体实现中,对父类的方法进行了重写,通过一个传入的参数Filename对该文件进行读取,得到其中的字符串,然后创建一个UTextAsset类型的资源文件,将字符串的内容赋给TextAsset的Text字段进行存储。

  • TextAssetFactoryNew.cpp

    与前一个文件大致相同,只不过没有具体的Create函数实现,仅仅通过NewObject返回了一个新的对象。

  • TextAssetEditorSettings.cpp

    这个类定义了若干关于插件属性的变量,包括:

    • 编辑器背景颜色
    • 编辑器文字颜色
    • 在编辑器窗口中使用的字体
    • 文本资源编辑器窗口周围的边距
  • TextAssetEditorStyle.h

    这个类继承自FSlateStyleSet(一个平板样式块,包含一组指定Slate外观的命名属性),可以参考:https://docs.unrealengine.com/en-US/API/Runtime/SlateCore/Styling/FSlateStyleSet/index.html,在这个类中,定义了一系列UI的外观,例如不同尺寸的图标。

  • TextAssetEditorToolkit.cpp

    这个类继承自FAssetEditorToolKit、FEditorUndoClient、FGCObject,负责初始化编辑器工具的相关功能,包括撤销,重新执行,对TextAsset的Text字段进行修改等。

    同时定义了UI的层级,如下所述:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    // create tab layout
    const TSharedRef<FTabManager::FLayout> Layout = FTabManager::NewLayout("Standalone_TextAssetEditor")
    ->AddArea
    (
    FTabManager::NewPrimaryArea()
    ->SetOrientation(Orient_Horizontal) // 垂直布局
    ->Split
    (
    // 此处是一个视图窗口
    FTabManager::NewSplitter()
    ->SetOrientation(Orient_Vertical) // 水平布局
    ->SetSizeCoefficient(0.66f) // 尺寸
    ->Split
    (
    FTabManager::NewStack()
    ->AddTab(GetToolbarTabId(), ETabState::OpenedTab)
    ->SetHideTabWell(true)
    ->SetSizeCoefficient(0.1f)

    )
    ->Split
    (
    FTabManager::NewStack()
    ->AddTab(TextAssetEditor::TabId, ETabState::OpenedTab)
    ->SetHideTabWell(true)
    ->SetSizeCoefficient(0.9f)
    )
    )
    );
  • STextAssetEditor.cpp

    这个类继承自SCompoundWidget,保存了编辑器的Slate格式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    void STextAssetEditor::Construct(const FArguments& InArgs, UTextAsset* InTextAsset, const TSharedRef<ISlateStyle>& InStyle)
    {
    TextAsset = InTextAsset;

    auto Settings = GetDefault<UTextAssetEditorSettings>();

    ChildSlot
    [
    SNew(SVerticalBox)

    + SVerticalBox::Slot()
    .FillHeight(1.0f)
    [
    SAssignNew(EditableTextBox, SMultiLineEditableTextBox)
    .BackgroundColor((Settings != nullptr) ? Settings->BackgroundColor : FLinearColor::White)
    .Font((Settings != nullptr) ? Settings->Font : FSlateFontInfo())
    .ForegroundColor((Settings != nullptr) ? Settings->ForegroundColor : FLinearColor::Black)
    .Margin((Settings != nullptr) ? Settings->Margin : 4.0f)
    .OnTextChanged(this, &STextAssetEditor::HandleEditableTextBoxTextChanged)
    .OnTextCommitted(this, &STextAssetEditor::HandleEditableTextBoxTextCommitted)
    .Text(TextAsset->Text)

    ]
    ];

    FCoreUObjectDelegates::OnObjectPropertyChanged.AddSP(this, &STextAssetEditor::HandleTextAssetPropertyChanged);
    }

    包括一系列设置,以及回调函数的注册等。