#input-event #bare-bones #performance #ui #keyboard-input

firewheel

(WIP) 高性能GUI的底层、简化版、"DIY"工具包

2个版本

0.0.1 2022年10月23日
0.0.0 2022年10月23日

#36 in #bare-bones

MIT/Apache

125KB
3K SLoC

Firewheel

Documentation Crates.io License

此包还在开发中。它尚未准备好用于任何类型的用途。


Firewheel是一个低级别的、保留模式的、事件驱动的、简化版、"DIY"工具包,用于制作高性能GUI。它不是一个包含大量现成小部件的完整GUI框架,而是一个帮助您构建自己的小部件和GUI系统的工具包。

该项目源于对高性能GUI工具包的需求,用于Meadowlark。Meadowlark的GUI非常不寻常(就通用GUI工具包而言),因为它包含大量自定义小部件、自定义布局逻辑、自定义渲染逻辑(使用着色器)以及独特的性能优化挑战。因此,我最终决定开发一个适合Meadowlark(以及我个人编码工作流程)需求的内部工具包。

如果您正在寻找一个易于使用/功能丰富的Rust GUI工具包,请查看以下GUI工具包之一(顺便说一句,根据您对“简单”的定义,您可能仍然会喜欢使用Firewheel ;))

工作原理

  • 层系统
    • 通过定义独立的“层”(小部件将其内容绘制到上的纹理)来执行渲染,然后将这些层组合在一起以获得最终输出。可以将小部件分配到任何层。
    • 每个小部件在其所属层中都有自己的专用矩形区域。小部件不能在其分配的区域外绘制,并且同一层中的多个小部件的区域不能重叠。由于这些限制,仅需要重新绘制有脏小部件的区域来重新绘制层,而不是每次每帧都重新绘制整个层。没有脏小部件的层根本不需要重新绘制(这在具有多个不同面板/部分的复杂桌面应用程序GUI中很常见)。
    • 任何层都可以通过简单地更改其内部偏移量(就像游戏引擎中的摄像机一样)有效地用作“滚动区域”。超出层边界之外的区域将自动从渲染和输入逻辑中裁剪。
    • 层自动打包到尽可能少的纹理中,以节省GPU内存并因此提高性能。
  • 小部件组织
    • 小部件不能包含其他小部件,也不能包含对其他小部件的引用。每个小部件只负责自己的逻辑和渲染,并且仅通过自定义事件与外界进行通信。
    • 没有“小部件树”或DOM。每个小部件本质上都是“根级别”,您可以在代码中以任何您喜欢的顺序组织它们。
    • 没有“容器”或“面板”小部件。您只需将所有背景定义为一系列矩形、线条和/或纹理,在“背景”层上进行单次绘制,然后在小部件层上绘制。当然,您可以在应用程序中创建任意数量的背景层和小部件层。
  • 布局系统
    • 小部件的布局是通过一个抽象矩形区域树来实现的。每个区域包含一个内部锚点、一个父锚点,以及这两个点之间的偏移量。没有“Flexbox”、“边距”或“填充”逻辑。
    • 每个区域的大小、锚点和锚点偏移量都是手动定义的。然而,容器(父)区域的大小或锚点偏移量的更改将自动更新其子区域的位置。
    • 只有小部件区域才允许绘制到屏幕上。容器(父)区域是完全抽象的,小部件区域不能是容器区域。
    • 任何区域都可以设置为显式可见/不可见。显式不可见的区域及其所有子区域将自动从渲染和输入逻辑中裁剪。
  • 指针(鼠标)输入逻辑
    • 小部件可以请求接收/停止接收指针输入事件。只有选择接收指针输入事件的 widgets 会收到指针输入事件。
    • 指针输入从具有最高 z-顺序值的层开始,然后沿着层列表向下工作,直到捕获到事件。
    • 指针输入通过仅调用包含指针位置的层和父区域,然后沿着区域树向下直到捕获到事件来优化。一旦捕获到事件,就停止遍历树。
    • 小部件可以请求“锁定”/“解锁”指针。锁定了指针的小部件即使在指针超出小部件分配区域边界的情况下也会接收到指针输入事件,这可以用于创建拖动手势。一次只能有一个小部件锁定指针。
    • 小部件可以请求接收/停止接收鼠标按下事件,无论位置如何,这可以实现如通过点击外部来关闭弹出窗口的行为。
    • 小部件可以标记自己为仅输入,这意味着它只监听指针输入事件而不绘制任何内容到屏幕上。这可以用来创建拖动手柄或拖放目标。
    • 每个指针输入事件都随键盘修饰符一起发送。
  • 键盘输入逻辑
    • 小部件可以请求接收/停止接收按键事件。只有选择接收按键事件的 widgets 会收到按键输入事件。
    • 小部件还可以请求接收/停止接收文本组合事件。一次只能将一个 widgets 分配为接收文本组合事件。
  • 动画逻辑
    • 小部件可以请求接收/停止接收“动画”输入事件,这是一个每帧发送的事件。只有选择接收此事件的 widgets 会收到此事件。
  • 样式化 & 自定义绘图
    • 没有预定义的样式表。您可以为您的 widgets/application 定义任何自定义样式系统。
    • Firewheel 提供了一个相对容易使用的由 femtovg(https://github.com/femtovg/femtovg)提供的 GPU 加速绘图 API。
    • 小部件还可以使用自定义着色器进行渲染。
  • 可移植性
    • 跨平台支持(仅依赖于 OpenGL (ES) 3.0+)。请自带窗口库和事件循环!
    • 内置高DPI支持。Firewheel使用逻辑像素坐标。

非目标

  • 不支持多行文本(至少目前是这样)。
  • 没有包含丰富的现成小部件。仅包含一些基本小部件,如按钮、切换按钮、标签、旋转器、滚动条、分隔符、下拉菜单和单行文本输入。
  • 没有类似于“Flexbox”的布局系统,因此这个库并不适用于Web或移动应用。
  • 没有窗口库或事件循环逻辑。您必须自己提供。 (请查看示例了解如何操作。)
  • 此工具包不保证您的GUI在没有相关知识的情况下能以最佳或正确的方式运行。使用此工具包需要了解如何最优地创建GUI的层和区域。(我可能会稍后创建一个指南。)

常见问题解答

  • 为什么叫做“Firewheel”?
    • Firewheel 是一种原产于美国中部的野花。这是遵循Meadowlark项目的一个惯例,即使用该地区(或与自然相关的事物)的本地动物/植物命名事物。
    • 这种野花的鲜艳色彩代表着屏幕上的绘图元素,“fire”则暗示了此工具包的高性能目标。

依赖项

~9MB
~97K SLoC