lv_bevy_ecs
Safe Rust bindings to the LVGL library using bevy_ecs. Compatible with #![no_std] environments by default.
What is an ECS?
ECS stands for Entity Component System. You can think of it as a database with rows (entities), columns (components) and jobs (systems).
You have to move LVGL objects into this database, so that they don't go out of scope and get deallocated. Bevy's Observers will mirror these database operations to LVGL's world.
But I don't want to use an ECS...
Enabling the no_ecs feature unlocks some functions that allow you to bring your own storage solution.
If you don't care about storage at all, and know in advance that a Widget will live for the rest of the program's execution,
you can call Widget::leak() to leak memory and prevent calling the destructor.
Check out no_ecs.rs on how to use these.
Usage
It is highly recommended to read Chapter 14 of the Unofficial Bevy Cheat Book before using this library.
- Create a project with
cargo neworesp-generate, then
-
This package depends on lightvgl-sys to generate the raw unsafe bindings. It needs an environment variable called
DEP_LV_CONFIG_PATHthat specifies the path to the folder containinglv_conf.hfile.It is recommended to put it into
.cargo/config.toml
[]
= { = true, = "." }
- You have to obtain a World instance with
LvglWorld::default();. This is a global variable, it can be stored in a LazyLock or passed around in an Arc<Mutex<>> if needed elsewhere than in main().
# use LvglWorld;
# use ;
static WORLD: = new;
-
Last thing is to calculate frametime and call these LVGL functions in every loop cycle
If you are running this inside another framework (like FreeRTOS), you should use its tick counter instead to get precise and constant framerate.
# use *;
# use ;
#
let mut prev_time = now;
// ...
loop
Check the documentation and the examples for further usage.
Running the demo
Building for embedded
There is an example project targeting the Cheap Yellow Display (ESP32) with std enabled: lvgl-bevy-demo
LVGL Global Allocator
A global allocator for Rust leveraging the LVGL memory allocator is provided, but not enabled by default.
Can be enabled with the feature lvgl_alloc. This will make all dynamic memory to be allocated by LVGL internal memory manager.
Features
- Displays
- Widgets
- Widget functions
- Events
- Styles
- Input devices
- Animations
- Timers
- Async calls
- Subjects
- Logging
- LVGL allocator
- "no_ecs" mode
- #![no_std] compatibility
- LVGL docstrings
- Auto-generated enums
- File system
- Custom fonts
- Snapshots
- Non-widget functions
- Layouts
- XML UI
Compatibility table
| lv_bevy_ecs | bevy_ecs | lightvgl-sys | LVGL |
|---|---|---|---|
| 0.6.2 | 0.17.3 | 9.4.3 | 9.4.0 |
| 0.6.1 | 0.17.3 | 9.4.2 | 9.4.0 |
| 0.5.2 | 0.17.3 | 9.4.2 | 9.4.0 |
| 0.5.0 | 0.17.2 | 9.4.0 | 9.4.0 |
| 0.4.0 | 0.17.2 | 9.3.0 | 9.3.0 |
| 0.3.0 | 0.16.0 | 9.3.0 | 9.3.0 |
| 0.2.0 | 0.16.0 | 9.2.0 | 9.2.2 |
Contributing
Feel free to open issues for features you find important and missing. I am not completely satisfied with the API, so open to API improvement ideas as well.
Troubleshooting
#[ctor]/#[dtor] is not supported on the current target
You are probably on RISC-V. Please help your architecture get upstreamed into rust-ctor.
Until then set default-features = false and manually call lv_init(); in the main function.
Thanks
This project heavily builds upon the work in the the original lv_binding_rust repo.