use derive_setters::Setters; use glam::{vec2, Affine2}; use hui_painter::{paint::command::{PaintRectangle, PaintTransform}, texture::TextureHandle}; use crate::{ element::{MeasureContext, ProcessContext, UiElement}, layout::{compute_size, Size, Size2d}, measure::Response, rect::{Corners, FillColor}, }; #[derive(Setters)] #[setters(no_std, prefix = "with_")] pub struct Image { /// Image handle to draw #[setters(skip)] pub image: TextureHandle, /// Size of the image. /// /// - If one of the dimensions is `Size::Auto`, the image will be scaled to fit the other dimension\ /// (aspect ratio is preserved) /// - If both dimensions are `Size::Auto`, the image will be drawn at its original size /// - All other values behave as expected #[setters(into)] pub size: Size2d, /// Color of the image /// /// Image will get multiplied/tinted by this color or gradient #[setters(into)] pub color: FillColor, /// Corner radius of the image #[setters(into)] pub corner_radius: Corners<f32>, } impl Image { pub fn new(handle: TextureHandle) -> Self { Self { image: handle, size: Size2d { width: Size::Auto, height: Size::Auto, }, color: (1., 1., 1.).into(), corner_radius: Corners::all(0.), } } } impl UiElement for Image { fn name(&self) -> &'static str { "image" } fn size(&self) -> Option<Size2d> { Some(self.size) } fn measure(&self, ctx: MeasureContext) -> Response { let dim = self.image.size(); let pre_size = compute_size(ctx.layout, self.size, dim.as_vec2()); Response { size: compute_size(ctx.layout, self.size, vec2( match self.size.height { Size::Auto => dim.x as f32, _ => (pre_size.y / dim.y as f32) * dim.x as f32, }, match self.size.height { Size::Auto => dim.x as f32, _ => (pre_size.y / dim.y as f32) * dim.x as f32, }, )), ..Default::default() } } fn process(&self, ctx: ProcessContext) { if !self.color.is_transparent() { ctx.paint_target.add( PaintTransform { transform: Affine2::from_translation(ctx.layout.position), child: PaintRectangle { size: ctx.measure.size, color: self.color, texture: Some(self.image), ..Default::default() }, } ); } } }