notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

anim.rs (4021B)


      1 use egui::{Pos2, Rect, Response, Sense};
      2 
      3 pub fn hover_expand(
      4     ui: &mut egui::Ui,
      5     id: egui::Id,
      6     size: f32,
      7     expand_size: f32,
      8     anim_speed: f32,
      9 ) -> (egui::Rect, f32, egui::Response) {
     10     // Allocate space for the profile picture with a fixed size
     11     let default_size = size + expand_size;
     12     let (rect, response) =
     13         ui.allocate_exact_size(egui::vec2(default_size, default_size), egui::Sense::click());
     14 
     15     let val = ui
     16         .ctx()
     17         .animate_bool_with_time(id, response.hovered(), anim_speed);
     18 
     19     let size = size + val * expand_size;
     20     (rect, size, response)
     21 }
     22 
     23 pub fn hover_expand_small(ui: &mut egui::Ui, id: egui::Id) -> (egui::Rect, f32, egui::Response) {
     24     let size = 10.0;
     25     let expand_size = 5.0;
     26     let anim_speed = 0.05;
     27 
     28     hover_expand(ui, id, size, expand_size, anim_speed)
     29 }
     30 
     31 pub static ICON_EXPANSION_MULTIPLE: f32 = 1.2;
     32 pub static ANIM_SPEED: f32 = 0.05;
     33 pub struct AnimationHelper {
     34     rect: Rect,
     35     center: Pos2,
     36     response: Response,
     37     animation_progress: f32,
     38     expansion_multiple: f32,
     39 }
     40 
     41 impl AnimationHelper {
     42     pub fn new(
     43         ui: &mut egui::Ui,
     44         animation_name: impl std::hash::Hash,
     45         max_size: egui::Vec2,
     46     ) -> Self {
     47         let id = ui.id().with(animation_name);
     48         let (rect, response) = ui.allocate_exact_size(max_size, Sense::click());
     49 
     50         let animation_progress =
     51             ui.ctx()
     52                 .animate_bool_with_time(id, response.hovered(), ANIM_SPEED);
     53 
     54         Self {
     55             rect,
     56             center: rect.center(),
     57             response,
     58             animation_progress,
     59             expansion_multiple: ICON_EXPANSION_MULTIPLE,
     60         }
     61     }
     62 
     63     pub fn no_animation(ui: &mut egui::Ui, size: egui::Vec2) -> Self {
     64         let (rect, response) = ui.allocate_exact_size(size, Sense::hover());
     65 
     66         Self {
     67             rect,
     68             center: rect.center(),
     69             response,
     70             animation_progress: 0.0,
     71             expansion_multiple: ICON_EXPANSION_MULTIPLE,
     72         }
     73     }
     74 
     75     pub fn new_from_rect(
     76         ui: &mut egui::Ui,
     77         animation_name: impl std::hash::Hash,
     78         animation_rect: egui::Rect,
     79     ) -> Self {
     80         let id = ui.id().with(animation_name);
     81         let response = ui.allocate_rect(animation_rect, Sense::click());
     82 
     83         let animation_progress =
     84             ui.ctx()
     85                 .animate_bool_with_time(id, response.hovered(), ANIM_SPEED);
     86 
     87         Self {
     88             rect: animation_rect,
     89             center: animation_rect.center(),
     90             response,
     91             animation_progress,
     92             expansion_multiple: ICON_EXPANSION_MULTIPLE,
     93         }
     94     }
     95 
     96     pub fn scale_1d_pos(&self, min_object_size: f32) -> f32 {
     97         let max_object_size = min_object_size * self.expansion_multiple;
     98 
     99         if self.response.is_pointer_button_down_on() {
    100             min_object_size
    101         } else {
    102             min_object_size + ((max_object_size - min_object_size) * self.animation_progress)
    103         }
    104     }
    105 
    106     pub fn scale_radius(&self, min_diameter: f32) -> f32 {
    107         self.scale_1d_pos((min_diameter - 1.0) / 2.0)
    108     }
    109 
    110     pub fn get_animation_rect(&self) -> egui::Rect {
    111         self.rect
    112     }
    113 
    114     pub fn center(&self) -> Pos2 {
    115         self.rect.center()
    116     }
    117 
    118     pub fn take_animation_response(self) -> egui::Response {
    119         self.response
    120     }
    121 
    122     // Scale a minimum position from center to the current animation position
    123     pub fn scale_from_center(&self, x_min: f32, y_min: f32) -> Pos2 {
    124         Pos2::new(
    125             self.center.x + self.scale_1d_pos(x_min),
    126             self.center.y + self.scale_1d_pos(y_min),
    127         )
    128     }
    129 
    130     pub fn scale_pos_from_center(&self, min_pos: Pos2) -> Pos2 {
    131         self.scale_from_center(min_pos.x, min_pos.y)
    132     }
    133 
    134     /// New method for min/max scaling when needed
    135     pub fn scale_1d_pos_min_max(&self, min_object_size: f32, max_object_size: f32) -> f32 {
    136         min_object_size + ((max_object_size - min_object_size) * self.animation_progress)
    137     }
    138 }