使用 C++ Mod 创建 GUI 页签
UE4SS 已包含用于渲染控制台 GUI 的 ImGui 库,构建自 UE4SS-RE/imgui 仓库。如何使用 ImGui 的类和方法渲染按钮、文本框等窗口对象,请参阅该仓库中的 ImGui 文档。
本指南介绍如何通过 C++ Mod 创建自定义 GUI 页签。原文以代码注释讲解,下面保留完整示例,并在代码后给出全部注释的中文说明:
#include <Mod/CppUserModBase.hpp>
#include <UE4SSProgram.hpp>
class MyAwesomeMod : public RC::CppUserModBase
{
private:
int m_private_number{33};
std::shared_ptr<GUI::GUITab> m_less_safe_tab{};
public:
MyAwesomeMod() : CppUserModBase()
{
ModName = STR("MyAwesomeMod");
ModVersion = STR("1.0");
ModDescription = STR("This is my awesome mod");
ModAuthors = STR("UE4SS Team");
// The 'register_tab' function will tell UE4SS to render a tab.
// Tabs registered this way will be automatically cleaned up when this C++ mod is destructed.
// The first param is the display name of your tab.
// The second param is a callback that UE4SS will use to render the contents of the tab.
// The param to the callback is a pointer to your mod.
register_tab(STR("My Test Tab"), [](CppUserModBase* instance) {
// In this callback, you can start rendering the contents of your tab with ImGui.
ImGui::Text("This is the contents of the tab");
// You can access members of your mod class with the 'instance' param.
auto mod = dynamic_cast<MyAwesomeMod*>(instance);
if (!mod)
{
// Something went wrong that caused the 'instance' to not be correctly set.
// Let's abort the rest of the function so that you don't access an invalid pointer.
return;
}
// You can access both public and private members.
mod->render_some_stuff(mod->m_private_number);
});
// The 'UE4SSProgram::add_gui_tab' function is another way to tell UE4SS to render a tab.
// This way of registering a tab will make you responsible for cleaning up the tab when your mod destructs.
// Failure to clean up the tab on mod destruction will result in a crash.
// It's recommended that you use 'register_tab' instead of this function.
m_less_safe_tab = std::make_shared<GUI::GUITab>(STR("My Less Safe Tab"), [](CppUserModBase* instance) {
// This callback is identical to the one used with 'register_tab' except 'instance' is always nullptr.
ImGui::Text("This is the contents of the less safe tab");
});
UE4SSProgram::get_program().add_gui_tab(m_less_safe_tab);
}
~MyAwesomeMod() override
{
// Because you created a tab with 'UE4SSProgram::add_gui_tab', you must manually remove it.
// Failure to remove the tab will result in a crash.
UE4SSProgram::get_program().remove_gui_tab(m_less_safe_tab);
}
auto on_ui_init() -> void override
{
// It's critical that you enable ImGui if you intend to use ImGui within the context of UE4SS.
// If you don't do this, a crash will occur as soon as ImGui tries to render anything, for example in your tab.
UE4SS_ENABLE_IMGUI()
}
auto render_some_stuff(int Number) -> void
{
auto calculated_value = Number + 1;
ImGui::Text(std::format("calculated_value: {}", calculated_value).c_str());
}
};
#define MY_AWESOME_MOD_API __declspec(dllexport)
extern "C"
{
MY_AWESOME_MOD_API RC::CppUserModBase* start_mod()
{
return new MyAwesomeMod();
}
MY_AWESOME_MOD_API void uninstall_mod(RC::CppUserModBase* mod)
{
delete mod;
}
}
代码注释译文:
register_tab告诉 UE4SS 渲染一个页签。通过此方式注册的页签会在 C++ Mod 析构时自动清理。第一个参数是页签显示名称,第二个参数是 UE4SS 用于渲染页签内容的回调;回调的参数是指向 Mod 的指针。- 在该回调中,可以开始使用 ImGui 渲染页签内容。
- 可以通过
instance参数访问 Mod 类的成员。如果某种错误导致instance未正确设置,应立即结束函数,避免访问无效指针。 - 可以访问公开成员和私有成员。
UE4SSProgram::add_gui_tab是告诉 UE4SS 渲染页签的另一种方式。通过这种方式注册后,必须自行负责在 Mod 析构时清理页签;未清理会导致崩溃。因此建议使用register_tab。- 传给
GUI::GUITab的回调与register_tab使用的回调相同,但这里的instance始终是nullptr。 - 由于使用
UE4SSProgram::add_gui_tab创建了页签,必须在析构函数中手动移除。未移除将导致崩溃。 - 如果打算在 UE4SS 上下文中使用 ImGui,必须在
on_ui_init中通过UE4SS_ENABLE_IMGUI()启用 ImGui。否则,ImGui 一旦尝试渲染任何内容(例如页签内容),就会崩溃。
原文:docs/guides/creating-gui-tabs-with-c++-mod.md · 固定提交 560411f18512 · 来源与 MIT 许可