====== ImGui 基础概念 ====== 如果您是初次使用 ** ImGui ** 包,我们希望您能认真阅读此页面,以保证您具备使用此包的基本概念。而后,您才可能知道您在自己的项目中需要什么,想要什么。 总体容阅读时间约为 20 min,请酌情参考。 本页面将呈现以下内容: * [[:manual:reference:package:extend:imgui:base:main_page#典型 ImGui 程序的代码布局 | 典型 ImGui 程序的代码布局]] * [[:manual:reference:package:extend:imgui:base:main_page#显示器方法(Open GL) | 显示器方法(Open GL)]] * [[:manual:reference:package:extend:imgui:base:main_page#应用(application)简要 | 应用(application)简要]] * [[:manual:reference:package:extend:imgui:base:main_page#向量(vec2/vec4) | 向量(vec2/vec4)]] * [[:manual:reference:package:extend:imgui:base:main_page#字体(font)简要 | 字体(font)简要]] * [[:manual:reference:package:extend:imgui:base:main_page#窗口(window)简要 | 窗口(window)简要]] * [[:manual:reference:package:extend:imgui:base:main_page#控件(widget)简要 | 控件(widget)简要]] * [[:manual:reference:package:extend:imgui:base:main_page#布局和组(group) | 布局和组(group)]] * [[:manual:reference:package:extend:imgui:base:main_page#画板(canvas) | 画板(canvas)]]
带简要的标题意为介绍部分,反之意为介绍全部。
----- \\ ===== 典型 ImGui 程序的代码布局 ===== ImGui 的所有内容均组织在名为 **application** 的,由系统提供的窗口内。 {{:manual:reference:package:extend:imgui:application.png}} 一个 application 内可以绘制多个**窗口(window)**。 每个**窗口**内可以拥有若干控件。 {{:manual:reference:package:extend:imgui:widget.png}} 我们可以使用一种典型代码结构来编写可视化工具: while !app.is_closed() app.prepare() ... app.render() end 在 **app.prepare()** 和 **app.render()** 间设计的布局的每个窗口(包括每个控件),都将以每一帧为单位染至**应用(application)**上。 ----- \\ ===== 显示器方法(Open GL) ===== Open GL 是 Dear ImGui 的后端,其方法与 Dear ImGui 无关。 在 ImGui 中保留并提供了对显示器的方法: ^**方法** ^**描述** ^ |**number** get_monitor_count() |获取系统使用显示器数量 | |**number** get_monitor_width(number monitor_id) |获取指定显示器的宽度(像素) | |**number** get_monitor_height(number monitor_id) |获取指定显示器的高度(像素) | 显示器 id 由系统分配。 例如:win10 下,显示器编号为 1~n,则**在 ImGui 中显示器 id 对应为 0~n-1**。 **单显示器下显示器 id 为 0。** ----- \\ ===== 应用(application)简要 ===== **application** 分为两种: ^application 申明方法 ^描述 ^ |[application] **fullscreen_application**(number monitor_id, string title) |创建全屏应用并返回应用对象 | |[application] **window_application**(number width, number height, string title) |创建窗口应用并返回应用对象 | 创建全屏应用需手动指定显示器 id。 创建窗口应用需指定长宽,需要创建与屏幕成比例的窗口,可以配合显示器方法(获取显示器长宽)使用。 **application** 支持设置内部所有窗口(window)的主题风格: ^设置主题方法 ^描述 ^ |void **style_color_classic**() |切换到经典主题 | |void **style_color_light**() |切换到亮色主题 | |void **style_color_dark**() |切换到暗色主题 | ----- \\ ===== 向量(vec2/vec4) ===== 在 Dear ImGui 中,有两类向量: * vec2:二维向量,常用于表示坐标或长宽 * vec4:四维向量,常用于表示有三通道和透明度的色彩(RGBA)
注意,四维色彩的值均在0~1之间(百分比表示)
ImGui 对此保留了以上设计: |[vec2] **vec2**(number x, number y) |返回二维向量对象,每个分量(x、y)可访问 | |[vec4] **vec4**(number x, number y, number z, number w) |返回四维向量对象,每个分量(x、y、z、w)可访问 | ----- \\ ===== 字体(font)简要 ===== ImGui 会为整个**应用**维护一个**字体栈**,每绘制一次窗口,都会自动使用**字体栈顶**的字体。 ImGui 为字体栈提供了以下方法: ^方法 ^描述 ^ |void **push_font**([font]) |将字体对象压入栈顶(使字体生效) | |void **pop_font**() |弹出字体栈栈顶对象(删除当前字体 ) | |[font] **get_font**() |获取栈顶对象(当前字体) | ImGui 为字体提供了专用的字体包 [[:manual:reference:package:extend:imgui:base:main_page |imgui_font【待更新】]] 和以下方法: |[font] **add_font**(string path, number size) |从路径中加载字体文件,指定字体大小,并返回字体对象 | |[font] **add_font_chinese**(string path, number size) |同上,适用于中文 | |[font] **add_font_default**(number size) |加载默认字体(英文),指定字体大小,并返回字体对象 | |[font] **add_font_extend**([imgui_font] data, number size) |加载 imgui_font 中的扩展字体,指定字体大小,并返回字体对象 | |[font] **add_font_extend_cn**([imgui_font] data, number size) |同上,适用于中文 |
对于以上需要加载字体文件的方法,都支持常用格式的字体文件。 而对于以上需要加载字体对象(imgui_font)的方法,则需要由 imgui_font 包额外提供。
import imgui import imgui_font var font0 = add_font_extend_cn(imgui_font.source_han_sans,25) var font1 = add_font_default(25) ... while !app.is_closed app.prepare() push_font(font0) ... # 此处控件使用 font0 字体 pop_font() push_font(font1) ... # 此处控件使用 font1 字体 app.render() end ----- \\ ===== 窗口(window)简要 ===== ImGui 的提供的窗口仅在**应用**中生效,即:应用内窗口。 窗口是控件的载体,每个应用内可以涵有若干窗口。 一般来说,通过如下的方式来设置窗口 ^方法 ^描述 ^ |void **set_window_pos**([vec2] pos) |设置当前窗口位置 | |void **set_window_size**([vec2] size) |设置当前窗口大小 | |void **begin_window**(string title_and_id, boolean is_open, array flags) |开始新窗口布局 | |void **end_window**() |结束窗口布局 | 对于以上方法做出解释。 例如,在 app 内绘制一个 window,然后渲染: while !app.is_closed app.prepare() begin_window("my_window##mw1", mw1_isopen, {}) set_window_pos(vec2(0,0)) set_window_size(vec2(get_widow_width(app),get_widow_height(app))) ... end_window() app.render() end
title_and_id
参数 title_and_id 表示该窗口的标题与 id 号,该参数由标题与 id 号两个字符串分构成,中间使用“##”隔开。
一个 title_and_id 可以没有 id 号,只有 title 标题的字符串。
合法的 title_and_id 例如:“title##1”、“title##a”、“1#”;非法的 title_and_id 有“1##”。
is_open
参数 is_open 必须一个变量的引用,即:必须是一个变量,而不能是一个具体的 boolean 常量。
这是因为每个 window 需要一个变量来记录是否被关闭(点击关闭按钮事件),从而达到检测窗口是否关闭的效果。
flags
参数 flags 为创建窗口时所携带的参数。包括**无标题栏**、**自适应大小**等。
----- \\ ===== 控件(widget)简要 ===== 互动类控件通常使用返回''boolean''类型的值,来表示其状态。 如按钮(button): ... begin_window(...) if button("click me!") # do something ... end_window() 控件种类繁多,不在此一一赘述。如有需要可以参考 [[:manual:reference:package:extend:imgui:widget:main_page |ImGui 控件]]文档。 \\ 标识符:一般用于右键菜单等,默认情况下标识符就是控件名,**但有些控件无 ID 时就要特别标示** 一般控件名可使用''title##id''的形式指定控件的标识符 ^方法 ^描述 ^ |void **push_id**(string title_and_id) |创建新标识符 | |void **pop_id**() |结束标识符 | ----- \\ ===== 布局和组(group) ===== ImGui支持使用''begin_group()''和''end_group()''一对方法标签,将若干控件组合为一个**组(group)**,并对其实施统一的布局行为。 以下改变布局的行为,仅对组内控件生效: ^方法 ^描述 ^ |void **begin_group**() |开始新组 | |void **end_group**() |结束组 | |void **separator**() |横向分割线 | |void **same_line**() |设置下一个控件为同一行 | |void **spacing**() |插入空格 | |void **indent**() |缩进 | |void **unindent**() |反缩进 | 另外还有树形节点,您可以理解为组(group)的树状形式: ^方法 ^描述 ^ |boolean **tree_node**(string label) |创建新的树节点 | |void **tree_pop**() |结束树节点 |
注意:只有 tree_node()返回真时才需要调用 tree_pop()
==== 焦点 ==== 可以粗浅理解为“当前选中的窗口或控件”。大部分I/O指令都作用于焦点控件(或窗口)上。焦点会被鼠标左键触发设置,您也可以自行设置焦点(根据逻辑)。 ^方法 ^描述 ^ |void **set_scroll_here**() |将滚动条滚动到当前位置 | |void **set_keyboard_focus_here**() |设置上一个控件为键盘焦点 | ----- \\ ===== 画板(canvas) ===== 画板提供了在**窗口**内绘图的系列方法。 ^方法 ^描述 ^ |void **add_line**([vec2] a, [vec2] b, [vec4] color, number thickness) |绘制线段 | |void **add_rect**([vec2] a, [vec2] b, [vec4] color, number rounding, number thickness) |绘制矩形线框 | |void **add_rect_filled**([vec2] a, [vec2] b, [vec4] color, number rounding) |填充矩形 | |void **add_quad**([vec2] a, [vec2] b, [vec2] c, [vec2] d, [vec4] color, number thickness) |绘制四边形线框 | |void **add_quad_filled**([vec2] a, [vec2] b, [vec2] c, [vec2] d, [vec4] color) |填充四边形 | |void **add_triangle**([vec2] a, [vec2] b, [vec2] c, [vec4] color, number thickness) |绘制三角形线框 | |void **add_triangle_filled**([vec2] a, [vec2] b, [vec2] c, [vec4] color) |填充三角形 | |void **add_circle**([vec2] centre, number radius, [vec4] color, number seg, number thickness) |画圆 | |void **add_circle_filled**([vec2] centre, number radius, [vec4] color, number seg) |填充圆 | |void **add_text**([font] font,number size, [vec2] pos, [vec4] color, string text) |绘制文字 | |void **add_image**([image] image, [vec2] a, [vec2] b) |绘制图片 |