最近研究接触了下ImGui, 发现这货结合Cocos2d-x系列引擎写游戏工具非常方便,据笔者分析,有如下优点:
- 不会污染游戏逻辑
- 复用游戏场景功能
- 无需美术提供工具资源,自动布局的菜单按钮,程序员轻松搞定
- 非常丰富的控件,可以写出非常易用的游戏工具,提高工具使用者体验和效率
- C++可用宏来控制,避免release游戏将GM工具发布出去了
于是笔者产生了将ImGui集成到EGNX引擎中的想法,本着复用原则,笔者先在github搜索一番,按stars数量排序(搜索优秀开源库的基本方法),点击查看搜索结果,按照常规,自然先使用了 c0i
的imguix
: https://github.com/c0i/imguix,但这个最是基于3.17.1的,而EGNX是基于cocos2d-x-4.0发展而来,因此经过简单修改,笔者使其支持了EGNX,并给作者提了PR: https://github.com/c0i/imguix/pull/32
如果到此为止,也就是简单集成而已,但经过多番查看github相关issues,发现imguix
不支持mutli-view-ports,与此同时也通过github
了解到imgui
官方仓库的docking
分支,是支持mutli-viewports的,也就是说ImGui的窗口可以拖出游戏窗口之外,因此笔者找到了这个仓库: https://github.com/Xrysnow/cocos2d-x-imgui
,通过简单了解发现,这个貌似也是基于imguix
优化的版本,在imguix
的基础上基于imgui
官方仓库的docking
分支,同时master分支主要支持cocos2d-x-4.0,于是笔者经过简单的修改,成功将该版本集成为EGNX的扩展,同时做了如下重点优化:
- Mac平台Mutli-Viewports拖动时导致游戏界面黑屏,因此禁用(tips: 跑了
imgui
官方的示例,也是无法拖出主窗口之外的) - 整理扩展管理单利类,重命名为: ImGuiEXT
- 修正概念ImGuiLayer其实仅仅做事件跟踪监测,并无实际渲染功能,因此重构为ImGuiEXTEventTracker并隐藏到扩展本身,不暴露给外部
- 重构为ImGuiEXT的addRenderLoop/removeRenderLoop接口来管理ImGui的渲染循环
- 提供非常简单易用的字体管理接口addFont,removeFont,clearFonts
- 优化ImGui的beginFrame, endFrame时机,使用者可以在addRenderLoop的渲染循环里处理ImGui的控件逻辑来直接安全地添加或删除游戏场景里的对象,有效避免迭代器被破坏
- 优化ImGuiEXT单利的生命周期管理,准确清理和初始化ImGui Context,避免destroyInstance后,再次ImGuiEXT::getInstacne使用时奔溃
-
DPI缩放支持 API:
ImGuiEXT::getInstance()->scaleAllByDPI(1.0);
- 在扩展内部自己计算需要赋值给
ImGui::GetIO()
的deltaTime,以避免暂停Director
后,ImGui报错 - 其他代码优化
Tips: 这里有个小点,就是之前版本EGNX或者cocos系列引擎,在Director暂停后会将帧率限制特别低,导致ImGui作为游戏内嵌工具的窗口拖动特别慢,笔者认为完全没必要,因此笔者加了宏来控制,详见:https://github.com/c4games/engine-x/commit/2d5fb7f77d671b3bb0f7ee5a4ded0e4fca2b8178
有了以上优化,EGNX的 ImGuiEXT 才真正达到易用和稳定性的程度,用法如下:
#include "ImGuiEXT/CCImGuiEXT.h"
USING_NS_CC;
USING_NS_CC_EXT;
class GameScene : public Scene {
public:
void onEnter() override
{
Scene::onEnter();
ImGuiEXT::getInstance()->addRenderLoop("#im01", CC_CALLBACK_0(GameScene::onImGuiDraw, this), this);
}
void onExit() override
{
ImGuiEXT::getInstance()->removeRenderLoop("#im01");
Scene::onExit();
}
void onImGuiDraw()
{
ImGui::Begin("window");
ImGui::Text("FPS=%.1f", 1.f / ImGui::GetIO().DeltaTime);
ImGui::End();
}
}
另外EGNX同时也写了test case,可以直接按照编译步骤跑ImGui的使用用例,效果如下
怎么样,是不是非常简单,以下贴出ImGuiEXT
和ImGui
官方链接,赶紧下载体验吧
- https://github.com/c4games/engine-x/tree/master/extensions/ImGuiEXT
- https://github.com/ocornut/imgui
非常感谢github的前辈们提供的cocos2dx imgui实现版本:
Tips:
- 本文是以
egnx
为例, 理论上cocos2d-x-4.0官方版本也是可以直接使用的 - 以上某些主观描述纯属个人观点,欢迎大神指正讨论
论坛其他相关帖子: