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 }