7

一个格式化文本信息版面的小玩意

 7 months ago
source link: https://blog.codingnow.com/2024/02/textcell.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一个格式化文本信息版面的小玩意

bgfx 提供了一组调试文本输出的 api ,可以把一些文本信息显示在屏幕上。这些 API 非常简陋,只是提供了一个文本模式缓冲区。离控制台还很远。

具体见 文档中 的 dbgText* 系列函数。

随着我们的游戏引擎中越来越多的信息需要展示,直接使用这些 api 就越发简陋了。最近萌发的想法是干脆使用 imgui 来绘制调试信息界面。但我又觉得保留 bgfx 自带的这个文本模式也有一些好处。

这个周末,孩子被爷爷奶奶带回老家去了。难得有不需要陪娃的一天。我周六一大早起来就在想写点什么。

最开始的想法是,使用基于 ncursors 的 UI 库。翻了一下没看见什么特别喜欢的。而且 bgfx 的文本模式并不是一个终端,可能还需要先把它改造成一个 VT100 终端先。

在 github 上搜索了一番,我用 VT100 Emulator 找到一些简单的库,没见到开箱即用的。感觉自己实现一个 VT100 终端也不算太复杂。大约 400 行代码就够了。主要是实现 ansi escape code ,有了这个,就能对接 ncursors 或 pdcursors 之类的库,然后文本界面 TUI 的选择也有很多。

然后,我发现了 imtui 这样一个有趣的玩具。它给 imgui 加了一个文本模式的 backend 。看起来还是挺炫酷的。但仔细一看,项目不太活跃很久没更新了。翻了下实现,也就几百行代码,花了半个小时就懂了。

imgui 输出的是 draw list ,即绘图指令列表。backend 把这些绘图指令传给真正的图形 api 画出来就好了。但是,这些绘图指令包含的是顶点数据流,而丢失了最初想画什么这个信息。

比如,UI 上的文字,在 draw list 里看到的就是两个三角形;菜单上的箭头,变成了一个三角形;圆形则变成了很多很多三角形……

如果你想在文本模式下重现这些图案,在不修改 imgui 的代码的前提下,只能靠猜。猜 draw list 里那些三角形到底在干什么。然后把 draw list 的顶点流切分开,还原成更高阶的绘图指令。imtui 这个库在这方面做的并不算太好,我一下就想到了许多猜测的方案,要廉价很多,更好实现。

花了一个上午,我模仿 imtui 自己写了一个新的 imgui 的 backend ,我是这样猜测的:

我为字体定义了一个特有的 texture id ,如果 draw list 里用到这个 id ,就一定是在绘制文字。然后,我使用自定义字形,把 ascii 码都从 imgui 的默认字体中替换掉,换成一个个 1x1 一个像素的字模,并把 ascii 写到贴图上。这样,在 drawlist 里发现文字绘制的时候,我直接根据 uv 取字体贴图,就能取到文本的 ascii 码。

然后,drawlist 里相邻两个三角形如果能构成一个矩形的话,就认为是背景框。在文本缓冲区上画带颜色的背景框还是很简单的。btw, imtui 里还真的写了一个三角形光栅化的代码,我觉得完全没有必要。

有些非矩形的三角形,也很容易判断出是什么方向的箭头,转换为文本字符。其它复杂的集合图形就直接扔掉。


等我把这一切做完,单独测试了一下新的 imgui backend 输出一屏幕的文本图案后。我对整个方案又产生了怀疑。如果做下去,去对接 bgfx api 倒是不难,但是,让 imgui 输出一大堆三角形,再想办法反向解析回来,又有多少意义呢?

其实,我并不需要一个完整的可交互的 UI 界面啊。只是为了调试时在屏幕展示一些信息而已。之前不好用,是因为没有做一个方便的版面编排接口。imgui 我倒是用过一段时间,它的 api 非常好用,尤其是 table api ,可以在屏幕上任意切分区块,在里面安放控件。

如果我只需要这么一个版面控制模块,并只支持文本输出的话,好像就解决了问题。

仔细想了一下,实现似乎也不难。我迅速扔掉了上午写的代码,下午重新实现了一套新的文本信息排版的库。最难的 API 设计部分 ImGui 已经做好了,抄就可以。具体实现几百行代码就能搞定。

https://github.com/cloudwu/textcell

到晚饭时间,基本就写完了。这种一天就能搞定的小玩具,真的是周末最好的消遣。

云风 提交于 February 4, 2024 02:41 PM | 固定链接


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK