Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved texture loading #3315

Merged
merged 61 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
86624e0
rework loading around `Arc<Loaders>`
jprochazk Sep 7, 2023
61c79cf
use `Bytes` instead of splitting api
jprochazk Sep 7, 2023
06aa357
remove unwraps in `texture_handle`
jprochazk Sep 7, 2023
e75a086
make `FileLoader` optional under `file` feature
jprochazk Sep 7, 2023
05eba4f
hide http load error stack trace from UI
jprochazk Sep 7, 2023
112f410
implement image fit
jprochazk Sep 7, 2023
e3a0219
support more image sources
jprochazk Sep 7, 2023
d305934
center spinner if we know size ahead of time
jprochazk Sep 7, 2023
0035b4e
allocate final size for spinner
jprochazk Sep 7, 2023
a58e085
improve image format guessing
jprochazk Sep 7, 2023
c5f88a9
remove `ui.image`, `Image`, add `RawImage`
jprochazk Sep 7, 2023
2e4496b
deprecate `RetainedImage`
jprochazk Sep 7, 2023
11686c7
`image2` -> `image`
jprochazk Sep 7, 2023
59b5835
add viewer example
jprochazk Sep 7, 2023
0dc3908
update `examples/image` + remove `svg` and `download_image` exapmles
jprochazk Sep 7, 2023
4c6d3c1
fix lints and tests
jprochazk Sep 7, 2023
db98a1c
fix doc link
jprochazk Sep 7, 2023
95f99e6
add image controls to `images` example
jprochazk Sep 8, 2023
d8c48ef
add more `From` str-like types
jprochazk Sep 8, 2023
3c78856
add api to forget all images
jprochazk Sep 8, 2023
e1ecd9d
fix max size
jprochazk Sep 8, 2023
8003e6b
do not scale original size unless necessary
jprochazk Sep 8, 2023
42ce39c
fix doc link
jprochazk Sep 8, 2023
8c9dbaa
add more docs for `Image` and `RawImage`
jprochazk Sep 8, 2023
d208001
make paint_at `pub`
jprochazk Sep 8, 2023
e43d4a0
update `ImageButton` to use new `Image` API
jprochazk Sep 8, 2023
565cb65
fix double rendering
jprochazk Sep 8, 2023
45a911d
Merge branch 'master' into texture-loading-p2
jprochazk Sep 11, 2023
8517e1f
`SizeHint::Original` -> `Scale` + remove `Option` wrapper
jprochazk Sep 11, 2023
7f15f78
Update crates/egui/src/load.rs
jprochazk Sep 11, 2023
1498cad
remove special `None` value for `forget`
jprochazk Sep 11, 2023
269621a
Update crates/egui/src/load.rs
jprochazk Sep 11, 2023
b42b3a4
add more examples to `ui.image` + add `include_image` macro
jprochazk Sep 11, 2023
543ac15
Update crates/egui/src/ui.rs
jprochazk Sep 11, 2023
992a9ae
update `menu_image_button` to use `ImageSource`
jprochazk Sep 11, 2023
fcd5b83
`OrderedFloat::get` -> `into_inner`
jprochazk Sep 11, 2023
1c491f6
derive `Eq` on `SizedTexture`
jprochazk Sep 11, 2023
89d333a
add `id` to loaders + `is_installed` check
jprochazk Sep 11, 2023
6e0afd0
move `images` to demo + simplify `images` example
jprochazk Sep 11, 2023
3d8718d
log trace when installing loaders
jprochazk Sep 11, 2023
0461002
fix lint
jprochazk Sep 11, 2023
ab48e60
fix doc link
jprochazk Sep 11, 2023
a10c105
add more documentation
jprochazk Sep 11, 2023
1a92435
more `egui_extras::loaders` docs
jprochazk Sep 11, 2023
39ccb15
Update examples/images/src/main.rs
jprochazk Sep 11, 2023
0680a2a
update `images` example screenshots + readme
jprochazk Sep 11, 2023
e136fa6
remove unused `rfd` from `images` example
jprochazk Sep 11, 2023
400edd0
Update crates/egui_extras/src/loaders/ehttp_loader.rs
jprochazk Sep 11, 2023
89c537f
add `must_use` on `Image` and `RawImage`
jprochazk Sep 11, 2023
cc88beb
document `loaders::install` multiple call safety
jprochazk Sep 11, 2023
f3d5c45
Update crates/egui_extras/Cargo.toml
jprochazk Sep 11, 2023
84cda37
reshuffle `is_loader_installed`
jprochazk Sep 11, 2023
2bf7716
make `include_image` produce `ImageSource` + update docs
jprochazk Sep 11, 2023
0faf371
update `include_image` docs
jprochazk Sep 11, 2023
ae202ed
remove `None` mentions from loader `forget`
jprochazk Sep 11, 2023
e7ad4d8
inline `From` texture id + size for `SizedTexture`
jprochazk Sep 11, 2023
6dc60de
add warning about statically known path
jprochazk Sep 11, 2023
39b6877
change image load error + use in image button
jprochazk Sep 12, 2023
8d6c60f
add `.size()` to `Image`
jprochazk Sep 12, 2023
d51f182
Update crates/egui_demo_app/Cargo.toml
jprochazk Sep 12, 2023
fa5cb22
add explanations to image viewer ui
jprochazk Sep 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
support more image sources
  • Loading branch information
jprochazk committed Sep 7, 2023
commit e3a0219b038b39702d9f8f3739604bd0470c1f9e
4 changes: 4 additions & 0 deletions crates/egui/src/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ impl SizedTexture {
size: handle.size(),
}
}

pub fn size_f32(&self) -> Vec2 {
Vec2::new(self.size[0] as f32, self.size[1] as f32)
}
}

#[derive(Clone)]
Expand Down
124 changes: 95 additions & 29 deletions crates/egui/src/widgets/image.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::load::Bytes;
use crate::{load::SizeHint, load::TexturePoll, *};
use crate::load::TextureLoadResult;
use crate::{
load::{Bytes, SizeHint, SizedTexture, TexturePoll},
*,
};
use emath::Rot2;
use epaint::util::FloatOrd;
use epaint::{util::FloatOrd, RectShape};

/// An widget to show an image of a given size.
///
Expand Down Expand Up @@ -334,6 +337,7 @@
}

/// This type tells the [`Ui`] how to load the image.
#[derive(Clone)]
pub enum ImageSource<'a> {
/// Load the image from a URI.
///
Expand All @@ -344,6 +348,12 @@
/// See [`crate::load`] for more information.
Uri(&'a str),

/// Load the image from an existing texture.
///
/// The user is responsible for loading the texture, determining its size,
/// and allocating a [`TextureId`] for it.
Texture(SizedTexture),

/// Load the image from some raw bytes.
///
/// The [`Bytes`] may be:
Expand Down Expand Up @@ -393,6 +403,13 @@
Self::new(ImageSource::Uri(uri))
}

/// Load the iamge from an existing texture.

Check warning on line 406 in crates/egui/src/widgets/image.rs

View workflow job for this annotation

GitHub Actions / Spell Check

"iamge" should be "image".
///
/// See [`ImageSource::Texture`].
pub fn from_texture(texture: SizedTexture) -> Self {
Self::new(ImageSource::Texture(texture))
}

/// Load the image from some raw bytes.
///
/// See [`ImageSource::Bytes`].
Expand Down Expand Up @@ -489,44 +506,93 @@
}
self
}
}

impl<'a> Widget for Image2<'a> {
fn ui(self, ui: &mut Ui) -> Response {
let uri = match self.source {
ImageSource::Uri(uri) => uri,
fn load_texture(&self, ui: &Ui) -> TextureLoadResult {
match self.source.clone() {
ImageSource::Texture(texture) => Ok(TexturePoll::Ready { texture }),
ImageSource::Uri(uri) => ui.ctx().try_load_texture(
uri,
self.texture_options,
self.size.hint(ui.available_size()),
),
ImageSource::Bytes(uri, bytes) => {
ui.ctx().include_bytes(uri, bytes);
uri
ui.ctx().try_load_texture(
uri,
self.texture_options,
self.size.hint(ui.available_size()),
)
}
};
}
}

let available_size = ui.available_size();
match ui
.ctx()
.try_load_texture(uri, self.texture_options, self.size.hint(available_size))
{
Ok(TexturePoll::Ready { texture }) => {
let final_size = self.size.finalize(
available_size,
Vec2::new(texture.size[0] as f32, texture.size[1] as f32),
);
fn uri(&self) -> &str {
match self.source {
ImageSource::Uri(uri) | ImageSource::Bytes(uri, _) => uri,
// Note: texture source is never in "loading" state
ImageSource::Texture(_) => "<unknown>",
}
}

let (rect, response) = ui.allocate_exact_size(final_size, self.sense);
fn paint_at(&self, ui: &mut Ui, rect: Rect, texture: &SizedTexture) {
if !ui.is_rect_visible(rect) {
return;
}

let mut mesh = Mesh::with_texture(texture.id);
mesh.add_rect_with_uv(
rect,
Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)),
Color32::WHITE,
let mut mesh = Mesh::with_texture(texture.id);
mesh.add_rect_with_uv(
rect,
Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)),
Color32::WHITE,
);
ui.painter().add(Shape::mesh(mesh));

if self.bg_fill != Default::default() {
let mut mesh = Mesh::default();
mesh.add_colored_rect(rect, self.bg_fill);
ui.painter().add(Shape::mesh(mesh));
}

match self.rotation {
Some((rot, origin)) => {
// TODO(emilk): implement this using `PathShape` (add texture support to it).
// This will also give us anti-aliasing of rotated images.
egui_assert!(
self.rounding == Rounding::ZERO,
"Image had both rounding and rotation. Please pick only one"
);

let mut mesh = Mesh::with_texture(texture.id);
mesh.add_rect_with_uv(rect, self.uv, self.tint);
mesh.rotate(rot, rect.min + origin * rect.size());
ui.painter().add(Shape::mesh(mesh));
}
None => {
ui.painter().add(RectShape {
rect,
rounding: self.rounding,
fill: self.tint,
stroke: Stroke::NONE,
fill_texture_id: texture.id,
uv: self.uv,
});
}
}
}
}

impl<'a> Widget for Image2<'a> {
fn ui(self, ui: &mut Ui) -> Response {
match self.load_texture(ui) {
Ok(TexturePoll::Ready { texture }) => {
let final_size = self.size.finalize(ui.available_size(), texture.size_f32());
let (rect, response) = ui.allocate_exact_size(final_size, self.sense);
self.paint_at(ui, rect, &texture);
response
}
Ok(TexturePoll::Pending { .. }) => {
ui.spinner().on_hover_text(format!("Loading {uri:?}…"))
}
Ok(TexturePoll::Pending { .. }) => ui
.spinner()
.on_hover_text(format!("Loading {:?}…", self.uri())),
Err(err) => ui.colored_label(ui.visuals().error_fg_color, err.to_string()),
}
}
Expand Down
3 changes: 1 addition & 2 deletions examples/svg/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ impl eframe::App for MyApp {

ui.separator();

let max_size = ui.available_size();
ui.add(
egui::Image2::from_bytes("ferris.svg", include_bytes!("rustacean-flat-happy.svg"))
.size_hint(max_size),
.shrink_to_fit(),
);
});
}
Expand Down
Loading