Skip to content

Commit

Permalink
Remove IntoImTexture
Browse files Browse the repository at this point in the history
Functions should directly return texture type used by backend.
No automatic conversion. This simplify uses of API.
Everything is more straightforward.
  • Loading branch information
malikolivier committed Aug 13, 2018
1 parent 4a64647 commit 34b9460
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 48 deletions.
12 changes: 6 additions & 6 deletions imgui-examples/examples/custom_textures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn main() {

// Constant texture (define once)
ui.text("Constant texture");
let constant_texture = ui.make_texture::<_, _, Texture>(im_str!("#Constant"), || {
let constant_texture = ui.make_texture(im_str!("#Constant"), || {
let mut image_data: Vec<Vec<(f32, f32, f32, f32)>> = Vec::new();
for i in 0..100 {
let mut row: Vec<(f32, f32, f32, f32)> = Vec::new();
Expand All @@ -40,15 +40,15 @@ fn main() {
}
image_data.push(row);
}
Texture2d::new(&gl_ctx, image_data).unwrap()
Texture::from_data(&gl_ctx, image_data).unwrap()
});
let size = constant_texture.get_size();
ui.image(&constant_texture, (size.0 as f32, size.1 as f32))
.build();

// Changing texture (re-defined and swap texture for each frame)
ui.text("Variable texture");
let changing_texture = ui.replace_texture::<_, Texture>(im_str!("#Changing"), {
let changing_texture = ui.replace_texture(im_str!("#Changing"), {
let mut image_data: Vec<Vec<(f32, f32, f32, f32)>> = Vec::new();
for i in 0..100 {
let mut row: Vec<(f32, f32, f32, f32)> = Vec::new();
Expand All @@ -61,16 +61,16 @@ fn main() {
if t > 1.0 {
t = 0.0;
}
Texture2d::new(&gl_ctx, image_data).unwrap()
Texture::from_data(&gl_ctx, image_data).unwrap()
});
let size = changing_texture.get_size();
ui.image(&changing_texture, (size.0 as f32, size.1 as f32))
.build();

// Texture defined only once, however, you can dynamically draw on it.
ui.text("Draw on texture");
let draw_texture = ui.make_texture::<_, _, Texture>(im_str!("#Draw"), || {
Texture2d::empty(&gl_ctx, 100, 100).unwrap()
let draw_texture = ui.make_texture(im_str!("#Draw"), || {
Texture::from_texture_2d(Texture2d::empty(&gl_ctx, 100, 100).unwrap())
});
// Get the texture as a surface. It must first be converted to a
// `glium::Texture2d` object by using `Texture::from`.
Expand Down
48 changes: 47 additions & 1 deletion imgui-examples/examples/support_gfx/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use imgui::{FontGlyphRange, FrameSize, ImFontConfig, ImGui, ImGuiMouseCursor, ImVec4, Ui};
use imgui_gfx_renderer::{Renderer, Shaders};
use imgui_gfx_renderer::{Renderer, Shaders, Texture};
use std::time::Instant;

#[derive(Copy, Clone, PartialEq, Debug, Default)]
Expand Down Expand Up @@ -220,6 +220,12 @@ pub fn run<F: FnMut(&Ui) -> bool>(title: String, clear_color: [f32; 4], mut run_
};

let ui = imgui.frame(frame_size, delta_s);

let texture = ui.make_texture(im_str!("#STANDARD"), || gfx_load_texture(&mut factory));
ui.image(&texture, (100.0, 100.0)).build();
let texture = ui.replace_texture(im_str!("#CHANGE"), gfx_load_texture_change(&mut factory));
ui.image(&texture, (100.0, 100.0)).build();

if !run_ui(&ui) {
break;
}
Expand Down Expand Up @@ -270,3 +276,43 @@ fn update_mouse(imgui: &mut ImGui, mouse_state: &mut MouseState) {
imgui.set_mouse_wheel(mouse_state.wheel);
mouse_state.wheel = 0.0;
}

use gfx;

fn gfx_load_texture<F, R>(factory: &mut F) -> Texture<R>
where
F: gfx::Factory<R>,
R: gfx::Resources,
{
let mut data = Vec::new();
let (width, height) = (100, 100);
for i in 0..width {
for j in 0..height {
data.push(i as u8);
data.push(j as u8);
data.push(255u8);
data.push(255u8);
}
}
Texture::from_raw(factory, width, height, &data).unwrap()
}

fn gfx_load_texture_change<F, R>(factory: &mut F) -> Texture<R>
where
F: gfx::Factory<R>,
R: gfx::Resources,
{
static mut COUNT: u8 = 0;
let mut data = Vec::new();
let (width, height) = (100, 100);
for i in 0..width {
for j in 0..height {
data.push(i as u8);
data.push(j as u8);
data.push(unsafe { COUNT });
data.push(255u8);
}
}
unsafe { if COUNT == 255 { COUNT = 0 } else { COUNT += 1 } };
Texture::from_raw(factory, width, height, &data).unwrap()
}
46 changes: 39 additions & 7 deletions imgui-glium-renderer/src/im_texture.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::borrow::Cow;
use std::mem;
use std::ops::Deref;

use glium::backend::Facade;
use glium::texture::{PixelValue, RawImage2d, Texture2dDataSource, TextureCreationError};
use glium::Texture2d;
use imgui::{FromImTexture, ImTexture, ImTextureID, IntoImTexture};
use imgui::{FromImTexture, ImTexture, ImTextureID};

/// Handle to a glium texture
///
Expand All @@ -19,12 +22,6 @@ impl ImTexture for Texture {
}
}

impl IntoImTexture<Texture2d> for Texture {
fn into_texture(texture: Texture2d) -> Texture {
Texture(texture)
}
}

impl Deref for Texture {
type Target = Texture2d;
fn deref(&self) -> &Self::Target {
Expand All @@ -37,3 +34,38 @@ impl FromImTexture for Texture {
unsafe { mem::transmute::<_, &Texture>(texture_id) }
}
}

impl Texture {
pub fn from_texture_2d(texture: Texture2d) -> Self {
Texture(texture)
}

pub fn from_data<'a, F, T>(facade: &F, data: T) -> Result<Self, TextureCreationError>
where
T: Texture2dDataSource<'a>,
F: Facade,
{
Texture2d::new(facade, data).map(Texture)
}

pub fn from_raw<F, P>(
facade: &F,
width: u32,
height: u32,
data: &[P],
) -> Result<Self, TextureCreationError>
where
F: Facade,
P: PixelValue,
{
Self::from_data(
facade,
RawImage2d {
data: Cow::Borrowed(data),
width,
height,
format: <P as PixelValue>::get_format(),
},
)
}
}
4 changes: 2 additions & 2 deletions imgui-glium-renderer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,14 @@ impl DeviceObjects {
let index_buffer = IndexBuffer::empty_dynamic(ctx, PrimitiveType::TrianglesList, 0)?;

let program = compile_default_program(ctx)?;
let texture = im_gui.register_font_texture::<_, _, Texture, _>(|handle| {
let texture = im_gui.register_font_texture(|handle| {
let data = RawImage2d {
data: Cow::Borrowed(handle.pixels),
width: handle.width,
height: handle.height,
format: ClientFormat::U8U8U8U8,
};
Texture2d::new(ctx, data)
Texture2d::new(ctx, data).map(Texture::from_texture_2d)
})?;
im_gui.set_texture_id(texture.get_id() as usize);

Expand Down
45 changes: 22 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub use sys::{
ImGuiTreeNodeFlags, ImGuiWindowFlags, ImTextureID, ImVec2, ImVec4,
};
use texture::TextureCache;
pub use texture::{AnyTexture, FromImTexture, ImTexture, IntoImTexture};
pub use texture::{AnyTexture, FromImTexture, ImTexture};
pub use trees::{CollapsingHeader, TreeNode};
pub use window::Window;
pub use window_draw_list::{ChannelsSplit, ImColor, WindowDrawList};
Expand Down Expand Up @@ -178,29 +178,29 @@ impl ImGui {
}
}
/// Register font texture returned by closure to [`ImGui`] instance.
pub fn register_font_texture<'a, F, T, U, E>(&mut self, f: F) -> Result<AnyTexture, E>
pub fn register_font_texture<'a, F, T, E>(&mut self, f: F) -> Result<AnyTexture, E>
where
F: FnOnce(FontTextureHandle<'a>) -> Result<T, E>,
U: 'static + IntoImTexture<T> + ImTexture,
T: 'static + ImTexture,
{
let io = self.io();
let mut pixels: *mut c_uchar = ptr::null_mut();
let mut width: c_int = 0;
let mut height: c_int = 0;
let mut bytes_per_pixel: c_int = 0;
let texture: U = unsafe {
let texture = unsafe {
sys::ImFontAtlas_GetTexDataAsRGBA32(
io.fonts,
&mut pixels,
&mut width,
&mut height,
&mut bytes_per_pixel,
);
IntoImTexture::into_texture(f(FontTextureHandle {
f(FontTextureHandle {
width: width as u32,
height: height as u32,
pixels: slice::from_raw_parts(pixels, (width * height * bytes_per_pixel) as usize),
})?)
})?
};
self.textures.register_texture(im_str!("#FONT"), texture);
Ok(self.textures.get_texture(im_str!("#FONT")).unwrap())
Expand Down Expand Up @@ -1425,13 +1425,13 @@ impl<'ui> Ui<'ui> {
/// extern crate imgui_glium_renderer;
///
/// use imgui::*;
/// use glium::Texture2d;
/// use imgui_glium_renderer::Texture;
/// use glium::backend::Facade;
///
/// fn make_a_texture<F: Facade>(ui: &Ui, facade: &F, data: Vec<Vec<(u8, u8, u8, u8)>>) {
/// let texture_handle = ui.replace_texture::<_, imgui_glium_renderer::Texture>(
/// let texture_handle = ui.replace_texture(
/// im_str!("#Texture Name ID"),
/// Texture2d::new(facade, data).unwrap(),
/// Texture::from_data(facade, data).unwrap(),
/// );
/// ui.image(&texture_handle, [100.0, 100.0]).build();
/// }
Expand Down Expand Up @@ -1687,29 +1687,29 @@ impl<'ui> Ui<'ui> {
/// extern crate imgui_glium_renderer;
///
/// use imgui::*;
/// use glium::Texture2d;
/// use imgui_glium_renderer::Texture;
/// use glium::backend::Facade;
/// use glium::Texture2d;
///
/// fn make_a_texture<F: Facade>(ui: &Ui, facade: &F) {
/// let texture_handle = ui.make_texture::<_, _, imgui_glium_renderer::Texture>(im_str!("#Texture Name ID"), || {
/// Texture2d::empty(facade, 100, 100).unwrap()
/// let texture_handle = ui.make_texture(im_str!("#Texture Name ID"), || {
/// Texture::from_texture_2d(Texture2d::empty(facade, 100, 100).unwrap())
/// });
/// // ... Do something with `texture_handle`
/// }
///
/// # fn main() {}
/// ```
pub fn make_texture<F, T, U>(&self, name: &ImStr, f: F) -> AnyTexture
pub fn make_texture<F, T>(&self, name: &ImStr, f: F) -> AnyTexture
where
F: FnOnce() -> T,
U: 'static + IntoImTexture<T> + ImTexture,
T: 'static + ImTexture,
{
let imgui = self.imgui();
if let Some(texture) = imgui.textures.get_texture(name) {
texture
} else {
let texture: U = IntoImTexture::into_texture(f());
imgui.textures.register_texture(name, texture);
imgui.textures.register_texture(name, f());
imgui.textures.get_texture(name).unwrap()
}
}
Expand All @@ -1730,26 +1730,25 @@ impl<'ui> Ui<'ui> {
/// extern crate imgui_glium_renderer;
///
/// use imgui::*;
/// use glium::Texture2d;
/// use imgui_glium_renderer::Texture;
/// use glium::backend::Facade;
///
/// fn make_a_texture<F: Facade>(ui: &Ui, facade: &F, data: Vec<Vec<(u8, u8, u8, u8)>>) {
/// let texture_handle = ui.replace_texture::<_, imgui_glium_renderer::Texture>(
/// let texture_handle = ui.replace_texture(
/// im_str!("#Texture Name ID"),
/// Texture2d::new(facade, data).unwrap(),
/// Texture::from_data(facade, data).unwrap(),
/// );
/// // ... Do something with `texture_handle`
/// }
///
/// # fn main() {}
/// ```
pub fn replace_texture<T, U>(&self, name: &ImStr, t: T) -> AnyTexture
pub fn replace_texture<T>(&self, name: &ImStr, t: T) -> AnyTexture
where
U: 'static + IntoImTexture<T> + ImTexture,
T: 'static + ImTexture,
{
let imgui = self.imgui();
let texture: U = IntoImTexture::into_texture(t);
imgui.textures.register_texture(name, texture);
imgui.textures.register_texture(name, t);
imgui.textures.get_texture(name).unwrap()
}
}
9 changes: 0 additions & 9 deletions src/texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,6 @@ impl Deref for AnyTexture {
}
}

/// Trait defining how an external type can be converted into a type implementing
/// [`ImTexture`].
///
/// Typically implemented to convert a native type (e.g. Texture2d from the
/// glium crate) to a type defined in the back-end implemnting [`ImTexture`].
pub trait IntoImTexture<T>: ImTexture {
fn into_texture(t: T) -> Self;
}

/// Trait defining how an object implementing [`ImTexture`] should be converted
/// back to the native texture type used by the back-end.
pub trait FromImTexture {
Expand Down

0 comments on commit 34b9460

Please sign in to comment.