Unreal Mode模式调用堆栈

此文章,主要是为了记录,在开发模式的插件(无图标)中,遇到的一些问题,调用堆栈过程中查看的函数层级关系。模式这块的坑是比较大的,从模式的注册、激活、保存关卡后模式的激活状态、新建关卡后模式的激活状态、切换关卡后模式的激活状态等各种各样的情况。那么接下来会从模式的注册与激活两方面来阐述,其他的情况视每个人的开发功能背景而定。

Mode模式

1. 注册Mode

Engine\Source\Editor\UnrealEd\Public\EditorModeRegistry.h

/**
 * 编辑器模式和工厂注册表
 */
class FEditorModeRegistry

来看看具体的注册函数

void FEditorModeRegistry::RegisterMode(FEditorModeID ModeID, TSharedRef<IEditorModeFactory> Factory)
{
    check(ModeID != FBuiltinEditorModes::EM_None);
    check(!ModeFactories.Contains(ModeID));

    ModeFactories.Add(ModeID, Factory);

    OnModeRegisteredEvent.Broadcast(ModeID);
    RegisteredModesChanged.Broadcast();
}

其中主要的关键点在于 往 ModeFactories 添加 模式的ID 和 工厂信息, 这里留一个彩蛋, 因为这个Map类型, 我们在激活模式的时候也会使用到.

注意:一般注册模式会放在模块的 StartupModule() 中。
需要注意的是注册自定义的Mode的时间节点不一定就会比UE本身的Mode注册的时间结点晚;毕竟我刚开始认为,我自己定义的模式,注册总在UE本身的Mode注册之后,后来打断点调用堆栈瞅了瞅,原来是自己错了。

2. 激活Mode

说到激活Mode,不得不说一个UE中强大的基础头文件,那就是Editor.h,为什么说它呢?见下函数
Engine\Source\Editor\UnrealEd\Public\Editor.h

/**
 * 提供对关卡编辑器的FEditorModeTools的访问
 */
UNREALED_API class FEditorModeTools& GLevelEditorModeTools();

GLevelEditorModeTools()函数 new了一个FEditorModeTools 对象,并且将创建的对象作为返回值返回。那么这个FEditorModeTools类又可以干什么呢?来看看它的定义:
Engine\Source\Editor\UnrealEd\Public\EditorModeManager.h

/**
 * 一个帮助程序类,用于存储各种编辑器模式的状态
 */
class UNREALED_API FEditorModeTools : public FGCObject, public FEditorUndoClient

一起看看在这个FEditorModeTools类中,有哪些函数

/*激活编辑器模式*/
void ActivateMode( FEditorModeID InID, bool bToggle = false );
/*禁用编辑器模式*/
void DeactivateMode(FEditorModeID InID);
/*如果传入的编辑器模式处于活动状态,则返回true*/
bool IsModeActive( FEditorModeID InID ) const;

再来看看类中有哪些属性

/**活动编辑器模式的列表*/
TArray< TSharedPtr<FEdMode> > ActiveModes;
/**我们可能会回收的先前活动的编辑器模式列表*/
TMap< FEditorModeID, TSharedPtr<FEdMode> > RecycledModes;

看到这些成员函数和成员属性, 顾名思义,这个类的功能有: 模式的激活、模式的禁用、判断模式是否被激活、激活模式的列表、激活模式的回收等等。

废话说了这么多,目的就是为了要说,在UE中,一般都是通过下面的方式去激活模式的:

GLevelEditorModeTools().ActivateMode(FEditorModeID);

下面就聊聊激活的两种方式

(1)点击图标激活

对于点击图标而言,必定是要有图标的,也就是说在模式那块,存在自己定义的模式图标,如上图所示,那么就需要注册一个有图标的模式,在注册的时候,传入 FSlateIcon 等参数 ,即可:
具体方法如下:

FEditorModeRegistry::Get().RegisterMode<自定义的Mode类名>(FEditorModeID, LOCTEXT(" ", " "), FSlateIcon(), true);

点击图标激活的话,会经过 点击 Click事件,然后激活点击的模式。具体调用层级结构如下:


(2)手动激活

对于手动激活而言,必定是没有图标的,也就是说在模式那块,没有自己定义的模式图标,如上图所示。那么如何去注册一个没有图标的模式呢?在注册的时候,直接省略 FSlateIcon 等参数,使用注册函数的默认参数。具体方法如下:

注册函数的默认参数
FEditorModeRegistry::Get().RegisterMode<自定义的Mode类名>(FEditorModeID);

手动激活的话,就返回到刚刚在第二点中说的,在 Editor.h 中的 GLevelEditorModeTools()函数 返回类型 FEditorModeTools 的 ActivateMode 函数,在想要激活的位置,去手动调用一下这个函数即可。例如:

GLevelEditorModeTools().ActivateMode(FEditorModeID);

这两种激活的方式,其实都会调用到FEditorModeTools 的 ActiveMode函数。

那就来看看 ,这个函数里到底有多少料吧,当然我不会把函数体全部搬过来,只说我认为的一些关键代码

  • ①是否是前面激活的回收模式,主要是为了 从A模式切换到B模式做准备
  • ②开篇说的彩蛋 Map,主要是判断此模式是否是已经注册过的
  • ③bool值判断 共同存活,欲激活的模式是否与其他的模式共同存在
  • ④ActiveModes 和 RecycledModes 的Add
  • ⑤CreatMode 与 构造 还有 Enter 调用到了自定义模式的 构造函数 和 Enter函数

3. 多种模式共同激活

我们可以看到 在ActiveMode 函数中,调用了 具体Mode的 IsCompatibleWith() 这样的一个函数,查看这个函数的翻译,这个函数就是为了让多种模式共同存在而服务的。


Engine\Source\Editor\UnrealEd\Public\EdMode.h

virtual bool IsCompatibleWith(FEditorModeID OtherModeID) const { return false; }

如果想要共同存活,我们可以在继承类中,重写这个函数,返回 true即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270