1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
use crate::*; pub struct TextureButton { geng: Rc<Geng>, theme: Rc<Theme>, core: WidgetCore, current: Rc<ugli::Texture>, next: Rc<ugli::Texture>, time: f64, } impl TextureButton { pub fn new(geng: &Rc<Geng>, theme: &Rc<Theme>, texture: &Rc<ugli::Texture>) -> Self { Self { geng: geng.clone(), theme: theme.clone(), core: WidgetCore::new(), current: texture.clone(), next: texture.clone(), time: 1.0, } } pub fn swap(&mut self, texture: &Rc<ugli::Texture>) { self.current = self.next.clone(); self.next = texture.clone(); self.time = 0.0; } pub fn rotate(&mut self) { self.current = self.next.clone(); self.time = 0.0; } pub fn ui<'a>(&'a mut self, action: Box<dyn FnMut() + 'a>) -> impl Widget + 'a { TextureButtonUI { geng: self.geng.clone(), theme: &self.theme, core: &mut self.core, texture: if self.time < 0.5 { &self.current } else { &self.next }, time: &mut self.time, action, } } } pub struct TextureButtonUI<'a> { geng: Rc<Geng>, theme: &'a Theme, core: &'a mut WidgetCore, action: Box<dyn FnMut() + 'a>, texture: &'a ugli::Texture, time: &'a mut f64, } impl<'a> AsMut<WidgetCore> for TextureButtonUI<'a> { fn as_mut(&mut self) -> &mut WidgetCore { self.core } } impl<'a> Widget for TextureButtonUI<'a> { fn core(&self) -> &WidgetCore { &self.core } fn core_mut(&mut self) -> &mut WidgetCore { &mut self.core } fn update(&mut self, delta_time: f64) { *self.time = partial_min(*self.time + delta_time * 4.0, 1.0); } fn draw(&mut self, framebuffer: &mut ugli::Framebuffer) { let angle = std::f32::consts::PI * ((*self.time as f32 * std::f32::consts::PI).cos() - 1.0); let mut v1 = Vec2::rotated( vec2(self.core().position().width() as f32 / 2.0, 0.0), angle, ); let mut v2 = Vec2::rotated( vec2(0.0, self.core().position().height() as f32 / 2.0), angle, ); if self.core().captured() { v1 *= self.theme.press_ratio; v2 *= self.theme.press_ratio; } let center = self.core().position().center().map(|x| x as f32); self.geng.draw_2d().textured( framebuffer, &[ draw_2d::TexturedVertex { a_pos: center - v1 - v2, a_vt: vec2(0.0, 0.0), a_color: Color::WHITE, }, geng::draw_2d::TexturedVertex { a_pos: center + v1 - v2, a_vt: vec2(1.0, 0.0), a_color: Color::WHITE, }, geng::draw_2d::TexturedVertex { a_pos: center + v1 + v2, a_vt: vec2(1.0, 1.0), a_color: Color::WHITE, }, geng::draw_2d::TexturedVertex { a_pos: center - v1 + v2, a_vt: vec2(0.0, 1.0), a_color: Color::WHITE, }, ], self.texture, if self.core().hovered() { self.theme.hover_color } else { self.theme.color }, ugli::DrawMode::TriangleFan, ) } fn handle_event(&mut self, event: &Event) { if let Event::Click { .. } = event { (self.action)(); } } }