From cb5e3c4892712dd1455f8284197dbaff1e9fed69 Mon Sep 17 00:00:00 2001 From: jprochazk <1665677+jprochazk@users.noreply.github.com> Date: Wed, 13 Sep 2023 10:00:06 +0200 Subject: [PATCH] use `ui.image`/`Image` over `RawImage` --- crates/egui/src/context.rs | 6 +-- crates/egui/src/lib.rs | 2 +- crates/egui/src/load.rs | 8 +++- crates/egui/src/ui.rs | 40 +---------------- crates/egui/src/widgets/button.rs | 2 +- crates/egui/src/widgets/image.rs | 44 +++++++++++++++---- crates/egui_demo_lib/src/color_test.rs | 4 +- .../egui_demo_lib/src/demo/widget_gallery.rs | 2 +- crates/egui_extras/src/image.rs | 2 +- crates/egui_plot/src/items/mod.rs | 13 +++--- examples/images/src/main.rs | 2 +- examples/screenshot/src/main.rs | 2 +- 12 files changed, 61 insertions(+), 66 deletions(-) diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 285a4254150..aca9d2baa48 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -1146,7 +1146,7 @@ impl Context { /// }); /// /// // Show the image: - /// ui.raw_image((texture.id(), texture.size_vec2())); + /// ui.image((texture.id(), texture.size_vec2())); /// } /// } /// ``` @@ -1692,14 +1692,14 @@ impl Context { let mut size = vec2(w as f32, h as f32); size *= (max_preview_size.x / size.x).min(1.0); size *= (max_preview_size.y / size.y).min(1.0); - ui.raw_image(SizedTexture::new(texture_id, size)) + ui.image(SizedTexture::new(texture_id, size)) .on_hover_ui(|ui| { // show larger on hover let max_size = 0.5 * ui.ctx().screen_rect().size(); let mut size = vec2(w as f32, h as f32); size *= max_size.x / size.x.max(max_size.x); size *= max_size.y / size.y.max(max_size.y); - ui.raw_image(SizedTexture::new(texture_id, size)); + ui.image(SizedTexture::new(texture_id, size)); }); ui.label(format!("{w} x {h}")); diff --git a/crates/egui/src/lib.rs b/crates/egui/src/lib.rs index 5c734baaee9..6baa0441098 100644 --- a/crates/egui/src/lib.rs +++ b/crates/egui/src/lib.rs @@ -84,7 +84,7 @@ //! ui.separator(); //! //! # let my_image = egui::TextureId::default(); -//! ui.raw_image((my_image, egui::Vec2::new(640.0, 480.0))); +//! ui.image((my_image, egui::Vec2::new(640.0, 480.0))); //! //! ui.collapsing("Click to see what is hidden!", |ui| { //! ui.label("Not much, as it turns out"); diff --git a/crates/egui/src/load.rs b/crates/egui/src/load.rs index 1682b1dfa1b..2e1cc1a471a 100644 --- a/crates/egui/src/load.rs +++ b/crates/egui/src/load.rs @@ -375,7 +375,13 @@ impl SizedTexture { impl From<(TextureId, Vec2)> for SizedTexture { #[inline] fn from((id, size): (TextureId, Vec2)) -> Self { - SizedTexture { id, size } + Self { id, size } + } +} + +impl<'a> From<&'a TextureHandle> for SizedTexture { + fn from(handle: &'a TextureHandle) -> Self { + Self::from_handle(handle) } } diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index 5b342b20039..362715a986c 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -5,7 +5,6 @@ use std::sync::Arc; use epaint::mutex::RwLock; -use crate::load::SizedTexture; use crate::{ containers::*, ecolor::*, epaint::text::Fonts, layout::*, menu::MenuState, placer::Placer, util::IdTypeMap, widgets::*, *, @@ -1585,44 +1584,7 @@ impl Ui { /// See also [`crate::Image`], [`crate::ImageSource`] and [`Self::raw_image`]. #[inline] pub fn image<'a>(&mut self, source: impl Into>) -> Response { - Image::new(source.into()).ui(self) - } - - /// Show an image created from a sized texture. - /// - /// You may use this method over [`Ui::image`] if you already have a [`TextureHandle`] - /// or a [`SizedTexture`]. - /// - /// ``` - /// # egui::__run_test_ui(|ui| { - /// struct MyImage { - /// texture: Option, - /// } - /// - /// impl MyImage { - /// fn ui(&mut self, ui: &mut egui::Ui) { - /// let texture = self - /// .texture - /// .get_or_insert_with(|| { - /// // Load the texture only once. - /// ui.ctx().load_texture( - /// "my-image", - /// egui::ColorImage::example(), - /// Default::default() - /// ) - /// }); - /// - /// // Show the image: - /// ui.raw_image((texture.id(), texture.size_vec2())); - /// } - /// } - /// # }); - /// ``` - /// - /// See also [`crate::RawImage`]. - #[inline] - pub fn raw_image(&mut self, texture: impl Into) -> Response { - RawImage::new(texture).ui(self) + Image::new(source).ui(self) } } diff --git a/crates/egui/src/widgets/button.rs b/crates/egui/src/widgets/button.rs index 38353b146d9..3334c9c430d 100644 --- a/crates/egui/src/widgets/button.rs +++ b/crates/egui/src/widgets/button.rs @@ -483,7 +483,7 @@ pub struct ImageButton<'a> { impl<'a> ImageButton<'a> { pub fn new(source: impl Into>) -> Self { Self { - image: Image::new(source.into()), + image: Image::new(source), sense: Sense::click(), frame: true, selected: false, diff --git a/crates/egui/src/widgets/image.rs b/crates/egui/src/widgets/image.rs index 90e7b516a22..687a1e208bb 100644 --- a/crates/egui/src/widgets/image.rs +++ b/crates/egui/src/widgets/image.rs @@ -32,14 +32,30 @@ pub struct Image<'a> { impl<'a> Image<'a> { /// Load the image from some source. - pub fn new(source: ImageSource<'a>) -> Self { - Self { - source, - texture_options: Default::default(), - image_options: Default::default(), - sense: Sense::hover(), - size: Default::default(), + pub fn new(source: impl Into>) -> Self { + fn new_mono(source: ImageSource<'_>) -> Image<'_> { + let size = if let ImageSource::Texture(tex) = &source { + // User is probably expecting their texture to have + // the exact size of the provided `SizedTexture`. + ImageSize { + maintain_aspect_ratio: false, + max_size: None, + fit: ImageFit::Exact(tex.size), + } + } else { + Default::default() + }; + + Image { + source, + texture_options: Default::default(), + image_options: Default::default(), + sense: Sense::hover(), + size, + } } + + new_mono(source.into()) } /// Load the image from a URI. @@ -52,8 +68,8 @@ impl<'a> Image<'a> { /// Load the image from an existing texture. /// /// See [`ImageSource::Texture`]. - pub fn from_texture(texture: SizedTexture) -> Self { - Self::new(ImageSource::Texture(texture)) + pub fn from_texture(texture: impl Into) -> Self { + Self::new(ImageSource::Texture(texture.into())) } /// Load the image from some raw bytes. @@ -157,18 +173,21 @@ impl<'a> Image<'a> { } /// Select UV range. Default is (0,0) in top-left, (1,1) bottom right. + #[inline] pub fn uv(mut self, uv: impl Into) -> Self { self.image_options.uv = uv.into(); self } /// A solid color to put behind the image. Useful for transparent images. + #[inline] pub fn bg_fill(mut self, bg_fill: impl Into) -> Self { self.image_options.bg_fill = bg_fill.into(); self } /// Multiply image color with this. Default is WHITE (no tint). + #[inline] pub fn tint(mut self, tint: impl Into) -> Self { self.image_options.tint = tint.into(); self @@ -183,6 +202,7 @@ impl<'a> Image<'a> { /// /// Due to limitations in the current implementation, /// this will turn off rounding of the image. + #[inline] pub fn rotate(mut self, angle: f32, origin: Vec2) -> Self { self.image_options.rotation = Some((Rot2::from_angle(angle), origin)); self.image_options.rounding = Rounding::ZERO; // incompatible with rotation @@ -195,6 +215,7 @@ impl<'a> Image<'a> { /// /// Due to limitations in the current implementation, /// this will turn off any rotation of the image. + #[inline] pub fn rounding(mut self, rounding: impl Into) -> Self { self.image_options.rounding = rounding.into(); if self.image_options.rounding != Rounding::ZERO { @@ -206,10 +227,12 @@ impl<'a> Image<'a> { impl<'a> Image<'a> { /// Returns the size the image will occupy in the final UI. + #[inline] pub fn calculate_size(&self, available_size: Vec2, image_size: Vec2) -> Vec2 { self.size.get(available_size, image_size) } + #[inline] pub fn size(&self) -> Option { match &self.source { ImageSource::Texture(texture) => Some(texture.size), @@ -217,6 +240,7 @@ impl<'a> Image<'a> { } } + #[inline] pub fn source(&self) -> &ImageSource<'a> { &self.source } @@ -224,6 +248,7 @@ impl<'a> Image<'a> { /// Get the `uri` that this image was constructed from. /// /// This will return `` for [`ImageSource::Texture`]. + #[inline] pub fn uri(&self) -> &str { match &self.source { ImageSource::Bytes(uri, _) | ImageSource::Uri(uri) => uri, @@ -256,6 +281,7 @@ impl<'a> Image<'a> { } } + #[inline] pub fn paint_at(&self, ui: &mut Ui, rect: Rect, texture: &SizedTexture) { paint_image_at(ui, rect, &self.image_options, texture); } diff --git a/crates/egui_demo_lib/src/color_test.rs b/crates/egui_demo_lib/src/color_test.rs index 4dc01cc50aa..ebbb3076ffc 100644 --- a/crates/egui_demo_lib/src/color_test.rs +++ b/crates/egui_demo_lib/src/color_test.rs @@ -88,7 +88,7 @@ impl ColorTest { let texel_offset = 0.5 / (g.0.len() as f32); let uv = Rect::from_min_max(pos2(texel_offset, 0.0), pos2(1.0 - texel_offset, 1.0)); ui.add( - RawImage::new((tex.id(), GRADIENT_SIZE)) + Image::from_texture((tex.id(), GRADIENT_SIZE)) .tint(vertex_color) .uv(uv), ) @@ -230,7 +230,7 @@ impl ColorTest { let texel_offset = 0.5 / (gradient.0.len() as f32); let uv = Rect::from_min_max(pos2(texel_offset, 0.0), pos2(1.0 - texel_offset, 1.0)); ui.add( - RawImage::new((tex.id(), GRADIENT_SIZE)) + Image::from_texture((tex.id(), GRADIENT_SIZE)) .bg_fill(bg_fill) .uv(uv), ) diff --git a/crates/egui_demo_lib/src/demo/widget_gallery.rs b/crates/egui_demo_lib/src/demo/widget_gallery.rs index 03d8fc35b92..8ea25ed8035 100644 --- a/crates/egui_demo_lib/src/demo/widget_gallery.rs +++ b/crates/egui_demo_lib/src/demo/widget_gallery.rs @@ -210,7 +210,7 @@ impl WidgetGallery { ui.add(doc_link_label("Image", "Image")); ui.allocate_ui(img_size * 2.0 + egui::Vec2::new(8.0, 0.0), |ui| { - ui.raw_image((texture.id(), img_size)); + ui.image((texture.id(), img_size)); ui.image(egui::include_image!("../../assets/icon.png")); }); ui.end_row(); diff --git a/crates/egui_extras/src/image.rs b/crates/egui_extras/src/image.rs index fcc30176de2..e1d0b330356 100644 --- a/crates/egui_extras/src/image.rs +++ b/crates/egui_extras/src/image.rs @@ -191,7 +191,7 @@ impl RetainedImage { // We need to convert the SVG to a texture to display it: // Future improvement: tell backend to do mip-mapping of the image to // make it look smoother when downsized. - ui.raw_image((self.texture_id(ui.ctx()), desired_size)) + ui.image((self.texture_id(ui.ctx()), desired_size)) } } diff --git a/crates/egui_plot/src/items/mod.rs b/crates/egui_plot/src/items/mod.rs index aefa6385e31..6d1e78795c5 100644 --- a/crates/egui_plot/src/items/mod.rs +++ b/crates/egui_plot/src/items/mod.rs @@ -1234,12 +1234,13 @@ impl PlotItem for PlotImage { Rect::from_two_pos(left_top_screen, right_bottom_screen) }; let screen_rotation = -*rotation as f32; - RawImage::new((*texture_id, image_screen_rect.size())) - .bg_fill(*bg_fill) - .tint(*tint) - .uv(*uv) - .rotate(screen_rotation, Vec2::splat(0.5)) - .paint_at(ui, image_screen_rect); + ui.add( + Image::from_texture((*texture_id, image_screen_rect.size())) + .bg_fill(*bg_fill) + .tint(*tint) + .uv(*uv) + .rotate(screen_rotation, Vec2::splat(0.5)), + ); if *highlight { let center = image_screen_rect.center(); let rotation = Rot2::from_angle(screen_rotation); diff --git a/examples/images/src/main.rs b/examples/images/src/main.rs index 193ab37ca48..656456cbb60 100644 --- a/examples/images/src/main.rs +++ b/examples/images/src/main.rs @@ -32,7 +32,7 @@ impl eframe::App for MyApp { .fit_to_fraction(vec2(1.0, 0.5)), ); ui.add( - egui::Image::new("https://picsum.photos/seed/1.759706314/1024".into()) + egui::Image::new("https://picsum.photos/seed/1.759706314/1024") .rounding(egui::Rounding::same(10.0)), ); }); diff --git a/examples/screenshot/src/main.rs b/examples/screenshot/src/main.rs index 9533a425a64..498d5013e0d 100644 --- a/examples/screenshot/src/main.rs +++ b/examples/screenshot/src/main.rs @@ -63,7 +63,7 @@ impl eframe::App for MyApp { }); if let Some(texture) = self.texture.as_ref() { - ui.raw_image((texture.id(), ui.available_size())); + ui.image((texture.id(), ui.available_size())); } else { ui.spinner(); }