bootsplash/
lib.rs

1use std::os::raw::c_void;
2
3use graphics::{
4    Logo,
5    lvgl::{
6        _lv_obj_t, LV_STATE_DEFAULT, lv_align_t_LV_ALIGN_CENTER, lv_anim_delete, lv_anim_init,
7        lv_anim_path_ease_in_out, lv_anim_set_duration, lv_anim_set_exec_cb, lv_anim_set_path_cb,
8        lv_anim_set_repeat_count, lv_anim_set_repeat_delay, lv_anim_set_reverse_delay,
9        lv_anim_set_reverse_time, lv_anim_set_values, lv_anim_set_var, lv_anim_start, lv_anim_t,
10        lv_obj_get_child, lv_obj_get_child_count, lv_obj_get_size, lv_obj_set_align,
11        lv_obj_set_style_opa, lv_obj_set_style_shadow_color,
12    },
13    theme,
14};
15
16mod error;
17
18pub use error::{Error, Result};
19
20pub struct Bootsplash {
21    animation: Box<lv_anim_t>,
22    _logo: Logo,
23}
24
25unsafe extern "C" fn load_animation_callback(object: *mut c_void, value: i32) {
26    static mut ANIMATED_PART: u8 = 2;
27    let object = object as *mut _lv_obj_t;
28
29    unsafe {
30        if (value == 255) || (value == 64) {
31            if ANIMATED_PART == 4 {
32                if value == 64 {
33                    ANIMATED_PART = 1;
34                }
35            } else {
36                ANIMATED_PART += 1;
37            }
38        }
39
40        let next_part = lv_obj_get_child(object, (ANIMATED_PART - 1) as i32);
41
42        if ANIMATED_PART.is_multiple_of(2) {
43            // lv_obj_set_style_shadow_width(next_part, 255 + 64 - value, LV_STATE_DEFAULT);
44
45            lv_obj_set_style_opa(next_part, (255 + 64 - value) as u8, LV_STATE_DEFAULT);
46
47            let previous_part = lv_obj_get_child(object, (ANIMATED_PART - 2) as i32);
48
49            lv_obj_set_style_opa(previous_part, value as u8, LV_STATE_DEFAULT);
50        } else {
51            // lv_obj_set_style_shadow_width(next_part, value, LV_STATE_DEFAULT);
52
53            lv_obj_set_style_opa(next_part, value as u8, LV_STATE_DEFAULT);
54
55            if ANIMATED_PART == 1 {
56                let previous_part = lv_obj_get_child(object, 3);
57
58                lv_obj_set_style_opa(previous_part, (255 + 64 - value) as u8, LV_STATE_DEFAULT);
59            } else {
60                let previous_part = lv_obj_get_child(object, (ANIMATED_PART - 2) as i32);
61
62                lv_obj_set_style_opa(previous_part, (255 + 64 - value) as u8, LV_STATE_DEFAULT);
63            }
64        }
65    }
66}
67
68impl Bootsplash {
69    pub async fn new(graphics_manager: &'static graphics::Manager) -> Result<Self> {
70        let _lock = graphics_manager.lock().await;
71
72        unsafe {
73            let current_screen = graphics_manager.get_current_screen()?;
74
75            let screen_size = lv_obj_get_size(current_screen);
76            let factor = Logo::get_factor(screen_size.scale(0.3));
77
78            let logo = Logo::new(current_screen, factor, theme::get_primary_color())?;
79
80            let logo_inner_object = logo.get_inner_object();
81
82            lv_obj_set_align(logo_inner_object, lv_align_t_LV_ALIGN_CENTER);
83            let child_count = lv_obj_get_child_count(logo_inner_object);
84            for i in 0..child_count {
85                let part = lv_obj_get_child(logo_inner_object, i as i32);
86
87                lv_obj_set_style_opa(part, 0, LV_STATE_DEFAULT);
88                lv_obj_set_style_shadow_color(
89                    part,
90                    theme::get_primary_color().into_lvgl_color(),
91                    LV_STATE_DEFAULT,
92                );
93            }
94
95            let mut s = Self {
96                animation: Box::new(lv_anim_t::default()),
97                _logo: logo,
98            };
99
100            lv_anim_init(&mut *s.animation);
101            lv_anim_set_var(&mut *s.animation, logo_inner_object as *mut c_void);
102            lv_anim_set_values(&mut *s.animation, 64, 255);
103            lv_anim_set_duration(&mut *s.animation, 500);
104            lv_anim_set_reverse_delay(&mut *s.animation, 0);
105            lv_anim_set_reverse_time(&mut *s.animation, 500);
106            lv_anim_set_repeat_delay(&mut *s.animation, 0);
107            lv_anim_set_repeat_count(&mut *s.animation, u32::MAX);
108            lv_anim_set_path_cb(&mut *s.animation, Some(lv_anim_path_ease_in_out));
109            lv_anim_set_exec_cb(&mut *s.animation, Some(load_animation_callback));
110            lv_anim_start(&*s.animation);
111
112            Ok(s)
113        }
114    }
115
116    pub async fn stop(self, graphics_manager: &'static graphics::Manager) -> Result<()> {
117        let _lock = graphics_manager.lock().await;
118
119        unsafe {
120            lv_anim_delete(self.animation.var, Some(load_animation_callback));
121        }
122
123        Ok(())
124    }
125}