gsimgui
简介
gsimui 简介
gsimgui是对 imgui docker 分支的一个封装。在 gs 通过 ffi 调用相关接口, 使用 glfw 对窗口进行封装。 gsimgui 具有以下优点
- 使用简单, 在将 imgui 以及 gflw 窗口的初始化 & 资源销毁全部封装 gs object 的声明周期中, 使用者无需关心。
- 结合 gs 的热更新功能,可以实现所见即所得的功能,有效的提升开发效率。
- 通过使用 ffi 创建的结构体来表示c++中的指针,可以让其使用方式与 imgui 基本一致,不需要学习成本。同时由于 ffi 创建的结构体是出于 gc 管理下的,所以使用者不需要关心其回收的问题。
IMGUI 简介
IMGUI(Immediate Mode GUI,即时模式图形用户界面) 是一种基于代码直接绘制用户界面的方法。与传统的保留模式(Retained Mode)GUI不同,IMGUI不会维护UI元素的持久状态,而是在每一帧中重新定义和绘制所有UI组件。这种模式在游戏开发、实时工具和调试界面中广泛应用,因其高效和灵活的特性而备受青睐。
核心特点:
- 无状态设计:UI元素的状态(如输入焦点、临时数据)由用户代码显式管理,而非由框架内部维护。
- 逐帧重建:每一帧都重新生成整个UI,适合动态内容或频繁变化的界面。
- 轻量级与快速迭代:代码驱动UI布局,无需复杂的设计工具,适合快速原型开发。
- 低内存开销:不长期存储UI元素数据,节省内存资源。
常见应用场景:
- 游戏调试工具:实时显示变量、调整参数(如Unity的Editor GUI)。
- 编辑器插件:快速构建工具界面。
- 原型开发:快速验证交互逻辑。
- 性能分析工具:动态展示实时数据。
关键注意事项
- 状态管理:通过变量控制UI状态(如
static bool show_window = true;
)。 - 性能优化:避免每帧创建大量UI元素,复杂界面可拆分到不同函数。
- 输入传递:确保将鼠标/键盘事件传递给IMGUI处理(如使用
ImGui_ImplSDL2_ProcessEvent
)。 - 样式定制:通过
ImGui::PushStyleColor()
或修改ImGuiStyle
结构体调整外观。
与其他库对比
特性 | IMGUI(如Dear ImGui) | 保留模式GUI(如Qt) |
---|---|---|
状态管理 | 用户显式管理 | 框架内部维护 |
开发速度 | 快速原型 | 需要设计工具 |
内存占用 | 低 | 较高 |
适用场景 | 实时工具、游戏 | 复杂应用、桌面软件 |
IMGUI以其简洁性和高效性,成为实时应用开发中的利器,尤其适合需要快速迭代和动态交互的场景。
在 GS 中使用
简单使用样例
加载 pkg.gsimgui.gsimgui.gs
, 然后通过 gsimgui.add_update_func
将 imgui 的绘制函数添加进去即可, 一个最简单了例子
import pkg.gsimgui;
void f() {
gsimgui.Text("hello gs imgui");
}
gsimgui.add_update_func((: f :));
gsimgui 的其他使用方式基本与原生的 imgui 无异, 可以参考 sample 里面的相关实现
gsimgui 对 imgui 传入为指针的参数的特殊处理
在 c++ 中,使用 imgui 经常会使用指针来后去值, 但是在 gs 中是没有这个概念的。所以 gsimgui 实现了以下结构体用于实现 c++ 的指针功能
-
ImBool:
用于 bool*, 在 gs 中使用
gsimgui.new_im_bool(bool val)
进行创建, 使用flag.value = 1
对其进行赋值, 使用flag.value
获取值 -
ImInt:
用于 int*, 在 gs 中使用
gsimgui.new_im_int(int val)
进行创建, 使用flag.value = 1
对其进行赋值, 使用flag.value
获取值 -
ImFloat:
用于 float*, 在 gs 中使用
gsimgui.new_im_float(float val)
进行创建, 使用flag.value = 1
对其进行赋值, 使用flag.value
获取值 -
ImVec2:
用于 float*, 在 gs 中使用
gsimgui.new_im_vec2(float x, float y)
进行创建, 使用flag.x = 1; flag.y = 2
对其进行赋值, 使用flag.x, flag.y
获取值 -
ImVec4:
用于 float*, 在 gs 中使用
gsimgui.new_im_vec4(float x, float y, float z, float w)
进行 创建, 使用flag.x = 1; flag.y = 2
对其进行赋值, 使用flag.x, flag.y
获取值 -
ImColor3:
用于 float*, 在 gs 中使用
gsimgui.new_im_color3(float r, float g, float b)
进行创建, 使用flag.r = 1; flag.g = 2
对其进行赋值, 使用flag.r, flag.b
获取值 -
ImColor4:
用于 float*, 在 gs 中使用
gsimgui.new_im_color4(float r, float g, float b, float a)
进行创建, 使用flag.r = 1; flag.g = 2
对其进行赋值, 使用flag.r, flag.b
获取值 -
ImString:
用于 char*, 在 gs 中使用
gsimgui.new_im_string(int size, string v)
进行创建, 使用flag.set_value(string new_val)
对其进行赋值, 使用flag.get_value()
获取值
使用样例
- button
- checkbox
- child_window
- color_picker
- combo
- input
- listbox
- radio_button
- text
- tooltip
- tree
- progress_bar
注意事项
*由于 gsimgui 是对 imgui 的封装,所以在使用 gsimgui 时,需要注意以下事项:
- 不要在 imgui 的绘制函数之外, 调用 imgui 的函数, 否则会导致 imgui 报错甚至崩溃, 需要在
gsimgui.add_update_func
中添加的回调中调用 imgui 的函数 - 由于 imgui 函数过多,目前 gsimgui 只对部分函数进行了封装, 后续会继续添加, 如果有需要,可以联系作者进行添加
- imgui 很多函数函数需要配对使用,比如
ImGui::Begin
和ImGui::End
是一对, 所以在使用时,需要注意配对使用, 否则会导致 imgui, 并且由于是不断的循环调用,报错会非常的多
组件接口
gsimgui.gs
枚举
WRAPMODE
GL_REPEAT = 0x2901,
GL_MIRRORED_REPEAT = 0x8370,
GL_CLAMP_TO_EDGE = 0x812F,
GL_CLAMP_TO_BORDER= 0x812D