diff --git a/Cargo.lock b/Cargo.lock index 59c6ab1c..3fdb63e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "ab_glyph" version = "0.2.11" @@ -829,6 +831,7 @@ dependencies = [ "egui", "epi", "glium", + "image", "ron", "serde", "tts", diff --git a/egui_glium/CHANGELOG.md b/egui_glium/CHANGELOG.md index 86918f88..e7929782 100644 --- a/egui_glium/CHANGELOG.md +++ b/egui_glium/CHANGELOG.md @@ -5,7 +5,8 @@ All notable changes to the `egui_glium` integration will be noted in this file. ## Unreleased * Remove "http" feature (use https://github.com/emilk/ehttp instead!). - +* Add `epi::NativeTexture` trait for glium painter +* Deprecate 'Painter::register_glium_texture' ## 0.14.0 - 2021-08-24 * Fix native file dialogs hanging (eg. when using [`rfd`](https://github.com/PolyMeilex/rfd)). diff --git a/egui_glium/Cargo.toml b/egui_glium/Cargo.toml index bdd3168a..9cea0432 100644 --- a/egui_glium/Cargo.toml +++ b/egui_glium/Cargo.toml @@ -39,6 +39,8 @@ tts = { version = "0.17", optional = true } # feature "time" chrono = { version = "0.4", optional = true } +[dev-dependencies] +image = { version = "0.23", default-features = false, features = ["png"] } [features] default = ["default_fonts"] diff --git a/egui_glium/examples/native_texture.rs b/egui_glium/examples/native_texture.rs new file mode 100644 index 00000000..6ea737f2 --- /dev/null +++ b/egui_glium/examples/native_texture.rs @@ -0,0 +1,111 @@ +//! Example how to use [epi::NativeTexture] with glium. +use epi::NativeTexture; +use glium::glutin; +use std::io::Cursor; + +fn create_display(event_loop: &glutin::event_loop::EventLoop<()>) -> glium::Display { + let window_builder = glutin::window::WindowBuilder::new() + .with_resizable(true) + .with_inner_size(glutin::dpi::LogicalSize { + width: 800.0, + height: 600.0, + }) + .with_title("egui_glium example"); + + let context_builder = glutin::ContextBuilder::new() + .with_depth_buffer(0) + .with_srgb(true) + .with_stencil_buffer(0) + .with_vsync(true); + + glium::Display::new(window_builder, context_builder, event_loop).unwrap() +} + +fn main() { + let event_loop = glutin::event_loop::EventLoop::with_user_event(); + let display = create_display(&event_loop); + + let mut egui = egui_glium::EguiGlium::new(&display); + //load image by image crate + let image = image::load( + Cursor::new(&include_bytes!("../../eframe/examples/rust-logo-512x512.png")[..]), + image::ImageFormat::Png, + ) + .unwrap() + .to_rgba8(); + let image_dimensions = image.dimensions(); + //mark as image + let image = glium::texture::RawImage2d::from_raw_rgba(image.into_raw(), image_dimensions); + //load to gpu memory + let native_texture = glium::texture::SrgbTexture2d::new(&display, image).unwrap(); + //allocate egui's texture id for GL texture + let texture_id = egui.painter_mut().register_native_texture(native_texture); + event_loop.run(move |event, _, control_flow| { + let mut redraw = || { + egui.begin_frame(&display); + + let mut quit = false; + + egui::SidePanel::left("my_side_panel").show(egui.ctx(), |ui| { + ui.heading(""); + if ui.button("Quit").clicked() { + quit = true; + } + }); + egui::Window::new("NativeTextureDisplay").show(egui.ctx(), |ui| { + ui.image(texture_id, egui::Vec2::new(128.0, 128.0)); + }); + let (needs_repaint, shapes) = egui.end_frame(&display); + + *control_flow = if quit { + glutin::event_loop::ControlFlow::Exit + } else if needs_repaint { + display.gl_window().window().request_redraw(); + glutin::event_loop::ControlFlow::Poll + } else { + glutin::event_loop::ControlFlow::Wait + }; + + { + use glium::Surface as _; + let mut target = display.draw(); + + let clear_color = egui::Rgba::from_rgb(0.1, 0.3, 0.2); + target.clear_color( + clear_color[0], + clear_color[1], + clear_color[2], + clear_color[3], + ); + + // draw things behind egui here + + egui.paint(&display, &mut target, shapes); + + // draw things on top of egui here + + target.finish().unwrap(); + } + }; + + match event { + // Platform-dependent event handlers to workaround a winit bug + // See: https://github.com/rust-windowing/winit/issues/987 + // See: https://github.com/rust-windowing/winit/issues/1619 + glutin::event::Event::RedrawEventsCleared if cfg!(windows) => redraw(), + glutin::event::Event::RedrawRequested(_) if !cfg!(windows) => redraw(), + + glutin::event::Event::WindowEvent { event, .. } => { + if egui.is_quit_event(&event) { + *control_flow = glium::glutin::event_loop::ControlFlow::Exit; + } + + egui.on_event(&event); + + display.gl_window().window().request_redraw(); // TODO: ask egui if the events warrants a repaint instead + } + + _ => (), + } + }); +} diff --git a/egui_glium/src/lib.rs b/egui_glium/src/lib.rs index 58102c17..2317e544 100644 --- a/egui_glium/src/lib.rs +++ b/egui_glium/src/lib.rs @@ -40,7 +40,8 @@ use { std::hash::{Hash, Hasher}, }; -pub use copypasta::ClipboardContext; // TODO: remove +pub use copypasta::ClipboardContext; +use std::borrow::BorrowMut; // TODO: remove pub struct GliumInputState { pub pointer_pos_in_points: Option, @@ -644,4 +645,8 @@ impl EguiGlium { &self.egui_ctx.texture(), ); } + + pub fn painter_mut(&mut self) -> &mut Painter { + self.painter.borrow_mut() + } } diff --git a/egui_glium/src/painter.rs b/egui_glium/src/painter.rs index 721898d6..fcd95d1b 100644 --- a/egui_glium/src/painter.rs +++ b/egui_glium/src/painter.rs @@ -241,8 +241,7 @@ impl Painter { id } - /// register glium texture as egui texture - /// Usable for render to image rectangle + #[deprecated = "Use: `NativeTexture::register_native_texture` instead"] pub fn register_glium_texture( &mut self, texture: glium::texture::SrgbTexture2d, @@ -319,3 +318,31 @@ impl Painter { } } } + +impl epi::NativeTexture for Painter { + type Texture = glium::texture::srgb_texture2d::SrgbTexture2d; + + fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId { + let id = self.alloc_user_texture(); + if let egui::TextureId::User(id) = id { + if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { + *user_texture = UserTexture { + pixels: vec![], + gl_texture: Some(native), + } + } + } + id + } + + fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) { + if let egui::TextureId::User(id) = id { + if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { + *user_texture = UserTexture { + pixels: vec![], + gl_texture: Some(replacing), + }; + } + } + } +} diff --git a/egui_web/CHANGELOG.md b/egui_web/CHANGELOG.md index aa5bea9d..1a5ce2de 100644 --- a/egui_web/CHANGELOG.md +++ b/egui_web/CHANGELOG.md @@ -4,8 +4,11 @@ All notable changes to the `egui_web` integration will be noted in this file. ## Unreleased -* Remove "http" feature (use https://github.com/emilk/ehttp instead!). +### Added +* Remove "http" feature (use https://github.com/emilk/ehttp instead!). +* `epi::NativeTexture` trait for webgl1 webgl2 painter +* Deprecate `Painter::register_webgl_texture` ## 0.14.1 - 2021-08-28 diff --git a/egui_web/src/webgl1.rs b/egui_web/src/webgl1.rs index a6ee4639..3d42a8ce 100644 --- a/egui_web/src/webgl1.rs +++ b/egui_web/src/webgl1.rs @@ -223,6 +223,7 @@ impl WebGlPainter { } } + #[deprecated = "Use: `NativeTexture::register_native_texture` instead"] pub fn register_webgl_texture(&mut self, texture: WebGlTexture) -> egui::TextureId { let id = self.alloc_user_texture_index(); if let Some(Some(user_texture)) = self.user_textures.get_mut(id) { @@ -370,6 +371,34 @@ impl epi::TextureAllocator for WebGlPainter { } } +impl epi::NativeTexture for WebGlPainter { + type Texture = WebGlTexture; + + fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId { + let id = self.alloc_user_texture_index(); + if let Some(Some(user_texture)) = self.user_textures.get_mut(id) { + *user_texture = UserTexture { + size: (0, 0), + pixels: vec![], + gl_texture: Some(native), + } + } + egui::TextureId::User(id as u64) + } + + fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) { + if let egui::TextureId::User(id) = id { + if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { + *user_texture = UserTexture { + size: (0, 0), + pixels: vec![], + gl_texture: Some(replacing), + } + } + } + } +} + impl crate::Painter for WebGlPainter { fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator { self diff --git a/egui_web/src/webgl2.rs b/egui_web/src/webgl2.rs index 36d80197..0ca6a4ce 100644 --- a/egui_web/src/webgl2.rs +++ b/egui_web/src/webgl2.rs @@ -202,6 +202,7 @@ impl WebGl2Painter { } } + #[deprecated = "Use: `NativeTexture::register_native_texture` instead"] pub fn register_webgl_texture(&mut self, texture: WebGlTexture) -> egui::TextureId { let id = self.alloc_user_texture_index(); if let Some(Some(user_texture)) = self.user_textures.get_mut(id) { @@ -349,6 +350,34 @@ impl epi::TextureAllocator for WebGl2Painter { } } +impl epi::NativeTexture for WebGl2Painter { + type Texture = WebGlTexture; + + fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId { + let id = self.alloc_user_texture_index(); + if let Some(Some(user_texture)) = self.user_textures.get_mut(id) { + *user_texture = UserTexture { + size: (0, 0), + pixels: vec![], + gl_texture: Some(native), + } + } + egui::TextureId::User(id as u64) + } + + fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) { + if let egui::TextureId::User(id) = id { + if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) { + *user_texture = UserTexture { + size: (0, 0), + pixels: vec![], + gl_texture: Some(replacing), + } + } + } + } +} + impl crate::Painter for WebGl2Painter { fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator { self diff --git a/epi/src/lib.rs b/epi/src/lib.rs index 8bb8f701..20271378 100644 --- a/epi/src/lib.rs +++ b/epi/src/lib.rs @@ -304,6 +304,18 @@ pub trait TextureAllocator { fn free(&mut self, id: egui::TextureId); } +/// Abstraction for platform dependent texture reference +pub trait NativeTexture { + type Texture; + + /// Bind native texture to egui texture + fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId; + + /// Change id's actual pointing texture + /// only for user texture + fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture); +} + /// How to signal the [`egui`] integration that a repaint is required. pub trait RepaintSignal: Send + Sync { /// This signals the [`egui`] integration that a repaint is required.