lv_bevy_ecs 0.5.0

Safe Rust bindings to the LVGL graphics library using Bevy's ECS framework
docs.rs failed to build lv_bevy_ecs-0.5.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: lv_bevy_ecs-0.6.5

lv_bevy_ecs

Safe Rust bindings to the LVGL library using bevy_ecs.

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.

Usage

It is highly recommended to read Chapter 14 of the Unofficial Bevy Cheat Book before using this library.

  1. Create a project with cargo new or esp-generate, then
        cargo add lv_bevy_ecs
  1. This package depends on lightvgl-sys to generate the raw unsafe bindings. It needs an environment variable called DEP_LV_CONFIG_PATH that specifies the path to the folder containing lv_conf.h file.

    It is recommended to put it into .cargo/config.toml

[env]
DEP_LV_CONFIG_PATH = { relative = true, value = "." }
  1. You have to obtain a World instance with LvglWorld::new();. This is a global variable, it can be stored in lazy_static! or passed around in an Arc<Mutex<>> if needed elsewhere than in main().
# use lazy_static::lazy_static;
# use lv_bevy_ecs::bevy::world::World;
# use lv_bevy_ecs::widgets::LvglWorld;
# use std::sync::Mutex;
#
lazy_static! {
    static ref WORLD: Mutex<World> = Mutex::new(LvglWorld::new());
}
  1. Last thing is to calculate frametime and call these LVGL functions in every loop cycle:
# use lv_bevy_ecs::functions::*;
# use std::time::{Instant, Duration};
#
let mut prev_time = Instant::now();
// ...
loop {
    let current_time = Instant::now();
    let diff = current_time.duration_since(prev_time);
    prev_time = current_time;
    // ...
    lv_tick_inc(diff);
    lv_timer_handler();
#    break;
}

Check the respective module documentations and the examples for further usage.

Consistent logging

You can forward LVGL logs to the log crate by calling lv_bevy_ecs::logging::connect(); during startup.

Or the other way around, calling lv_bevy_ecs::logging::lv_log_init(); will forward the log crate macros to LVGL's logger. This way you also have line numbers at the end of each message by default.

Using both will create an infinite loop and stack overflow.

If you use the logging macros from this crate (e. g. lv_bevy_ecs::info!("This is an info")) then the message will use the function name instead of module name as target, which makes it consistent with LVGL logging.

Don't forget to adjust the logging level on both sides!

See examples/custom_logging.rs for sample code.

Running the demo

sudo apt install libsdl2-dev

git clone git@github.com:SakiiCode/lv_bevy_ecs.git
cd lv_bevy_ecs
cargo run --example basic

Building for embedded

This package has been tested with ESP32 only.

You need three more env variables in config.toml and the PATH applied from ~/export-esp.sh

LIBCLANG_PATH="..."
CROSS_COMPILE="xtensa-esp32-elf"
BINDGEN_EXTRA_CLANG_ARGS="--sysroot ..."

LIBCLANG_PATH can be found in ~/export-esp.sh

BINDGEN_EXTRA_CLANG_ARGS sysroot can be found with xtensa-esp32-elf-ld --print-sysroot

Example project

There is an example project targeting the Cheap Yellow Display (ESP32) with std enabled: lvgl-bevy-demo

Partitions

It can happen that the project does not fit in the default main partition. To fix that you need to generate a partitions.csv with

cargo espflash partition-table -o partitions.csv --to-csv target/xtensa-esp32-espidf/release/partition-table.bin

and increase the factory partition size.

Then add this to espflash.toml:

[idf]
partition_table = "partitions.csv"

Upload speed

To increase upload speed set baudrate = 460800 in espflash.toml

Features

  • Displays
  • Widgets
  • Events
  • Styles
  • Input devices
  • Animations
  • Timers
  • Async calls
  • Subjects
  • Logging
  • Auto-generated enums
  • Copy C docs to rustdoc
  • #![no_std] compatibility
  • implement GlobalAlloc
  • File system
  • Custom fonts
  • Snapshots
  • Some widget functions
  • Layouts
  • XML UI

Compatibility table

lv_bevy_ecs bevy_ecs lightvgl-sys LVGL
0.5 0.17.2 9.4.0 9.4.0
0.4 0.17.2 9.3.0 9.3.0
0.3 0.16.0 9.3.0 9.3.0
0.2 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.