转载自邵晨峰的个人网站
最近在逛Github时发现了一个单文件跨平台零依赖的图形库nuklear,这使我产生了兴趣,一个大约两万行的程序,实现了很不错的效果,更神奇的是它是零依赖的,这意味着可以运用到类似单片机等特殊环境,于是我果断Fork了它开始了学习之路zoollcar/nuklear,下面我们分析下nuklear
图形库的源代码
综述
首先看一下官方提供的demo(win gui版),后面会一部分一部分的分析
/* win32 实现细节*/
while (running)
{
/* 输入部分 */
/* win32 实现细节 */
nk_input_begin(ctx);
/* input 细节 */
nk_input_end(ctx);
/* GUI 部分 */
if (nk_begin(ctx, "Demo", nk_rect(50, 50, 200, 200),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
enum {EASY, HARD};
static int op = EASY;
static int property = 20;
/* 固定小部件像素宽度(纵向布局) */
/* 创建小部件之前使用 nk_layout_xxx 来说明后面的小部件布局 */
nk_layout_row_static(ctx, 30/* 高度 */, 80/* 元素宽度 */, 1/* 个数 */);
if (nk_button_label(ctx, "button")){
/* 点击事件 */
fprintf(stdout, "button pressed\n");
}
/* 小部件横向动态布局(默认是纵向) */
nk_layout_row_dynamic(ctx, 30, 2);
if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
nk_layout_row_dynamic(ctx, 22, 1);
nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
}
nk_end(ctx);
/* 绘制部分 */
nk_gdi_render(nk_rgb(30,30,30)); /* win32 gui平台专用渲染 */
}
这里去除了win32实现细节,因为它本身虽然是跨平台的,但并不是所有部分都跨平台 整个程序可以分为输入部分,GUI部分,绘制部分,他们的关系是这样的:
graph TD;
输入部分--输入信息-->GUI部分;
GUI部分--绘制命令-->绘制部分;
在 nuklear
中一个称为上下文的变量会贯穿整个程序,其类型为nk_context
,其中记录了这个程序几乎所有的信息,包括输入结构体、整体样式、个个窗口、渲染命令缓冲区,它起着连接 nuklear 所有部分的功能
/* 上下文 */
struct nk_context {
struct nk_input input; /* 输入 */
struct nk_style style; /* 样式 */
struct nk_buffer memory; /* 缓冲区 */
struct nk_clipboard clip; /* 剪切板 */
nk_flags last_widget_state; /* 最近一个小部件状态 */
enum nk_button_behavior button_behavior; /* 按钮行为是默认还是被替换的 */
struct nk_configuration_stacks stacks;
float delta_time_seconds; /* 时间(秒) */
/* 其他细节 */
/* 窗口 */
int build;
int use_pool;
struct nk_pool pool;
struct nk_window *begin; /* 窗口链表 */
struct nk_window *end;
struct nk_window *active; /* 激活窗口 */
struct nk_window *current; /* 当前窗口 */
struct nk_page_element *freelist;
unsigned int count;
unsigned int seq;
};
输入部分
input API 负