Make ImTexture a newtype for additional type safety

This commit is contained in:
Tad Hardesty 2018-09-10 00:59:55 -07:00
parent fb7ea044e2
commit e9b1552f05
4 changed files with 50 additions and 21 deletions

View File

@ -227,7 +227,7 @@ impl<R: Resources> Renderer<R> {
self.bundle.slice.start = 0; self.bundle.slice.start = 0;
for cmd in draw_list.cmd_buffer { for cmd in draw_list.cmd_buffer {
if let Some(tex) = self.textures.get(cmd.texture_id as usize) { if let Some(tex) = self.textures.get(cmd.texture_id.into()) {
// cloning handles is okay, since they're Arcs internally // cloning handles is okay, since they're Arcs internally
self.bundle.data.tex = tex.clone(); self.bundle.data.tex = tex.clone();
} }

View File

@ -7,8 +7,8 @@ use glium::index::{self, PrimitiveType};
use glium::program; use glium::program;
use glium::texture; use glium::texture;
use glium::vertex; use glium::vertex;
use glium::{DrawError, GlObject, IndexBuffer, Program, Surface, Texture2d, VertexBuffer}; use glium::{DrawError, IndexBuffer, Program, Surface, Texture2d, VertexBuffer};
use imgui::{DrawList, FrameSize, ImDrawIdx, ImDrawVert, ImGui, Ui}; use imgui::{DrawList, FrameSize, ImDrawIdx, ImDrawVert, ImGui, Ui, Textures};
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt; use std::fmt;
use std::rc::Rc; use std::rc::Rc;
@ -81,6 +81,10 @@ impl Renderer {
}) })
} }
pub fn textures(&mut self) -> &mut Textures<Texture2d> {
&mut self.device_objects.textures
}
pub fn render<'a, S: Surface>(&mut self, surface: &mut S, ui: Ui<'a>) -> RendererResult<()> { pub fn render<'a, S: Surface>(&mut self, surface: &mut S, ui: Ui<'a>) -> RendererResult<()> {
let _ = self.ctx.insert_debug_marker("imgui-rs: starting rendering"); let _ = self.ctx.insert_debug_marker("imgui-rs: starting rendering");
let FrameSize { let FrameSize {
@ -128,12 +132,17 @@ impl Renderer {
self.device_objects self.device_objects
.upload_index_buffer(&self.ctx, draw_list.idx_buffer)?; .upload_index_buffer(&self.ctx, draw_list.idx_buffer)?;
let font_texture_id = self.device_objects.texture.get_id() as usize;
let mut idx_start = 0; let mut idx_start = 0;
for cmd in draw_list.cmd_buffer { for cmd in draw_list.cmd_buffer {
// We don't support custom textures...yet! let texture = match self.device_objects.textures.get(cmd.texture_id.into()) {
assert!(cmd.texture_id as usize == font_texture_id); Some(tex) => tex,
// if an invalid ID is supplied, fall back to the font
None => match self.device_objects.textures.get(0.into()) {
Some(tex) => tex,
// if the font is missing, which should never happen, skip
None => continue,
}
};
let idx_end = idx_start + cmd.elem_count as usize; let idx_end = idx_start + cmd.elem_count as usize;
@ -147,7 +156,7 @@ impl Renderer {
&self.device_objects.program, &self.device_objects.program,
&uniform! { &uniform! {
matrix: matrix, matrix: matrix,
tex: self.device_objects.texture.sampled() tex: texture.sampled()
}, },
&DrawParameters { &DrawParameters {
blend: Blend::alpha_blending(), blend: Blend::alpha_blending(),
@ -178,7 +187,7 @@ pub struct DeviceObjects {
vertex_buffer: VertexBuffer<ImDrawVert>, vertex_buffer: VertexBuffer<ImDrawVert>,
index_buffer: IndexBuffer<ImDrawIdx>, index_buffer: IndexBuffer<ImDrawIdx>,
program: Program, program: Program,
texture: Texture2d, textures: Textures<Texture2d>,
} }
fn compile_default_program<F: Facade>( fn compile_default_program<F: Facade>(
@ -231,13 +240,14 @@ impl DeviceObjects {
}; };
Texture2d::new(ctx, data) Texture2d::new(ctx, data)
})?; })?;
im_gui.set_texture_id(texture.get_id() as usize); let mut textures = Textures::new();
im_gui.set_texture_id(textures.insert(texture));
Ok(DeviceObjects { Ok(DeviceObjects {
vertex_buffer: vertex_buffer, vertex_buffer: vertex_buffer,
index_buffer: index_buffer, index_buffer: index_buffer,
program: program, program: program,
texture: texture, textures: textures,
}) })
} }
pub fn upload_vertex_buffer<F: Facade>( pub fn upload_vertex_buffer<F: Facade>(

View File

@ -4,7 +4,26 @@ use std::collections::HashMap;
use std::os::raw::c_void; use std::os::raw::c_void;
use sys; use sys;
pub type ImTexture = usize; #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ImTexture(usize);
impl ImTexture {
pub fn id(&self) -> usize {
self.0
}
}
impl From<usize> for ImTexture {
fn from(id: usize) -> Self {
ImTexture(id)
}
}
impl From<*mut c_void> for ImTexture {
fn from(ptr: *mut c_void) -> Self {
ImTexture(ptr as usize)
}
}
/// Represent an image about to be drawn. /// Represent an image about to be drawn.
/// See [`Ui::image`]. /// See [`Ui::image`].
@ -22,7 +41,7 @@ pub struct Image<'ui> {
} }
impl<'ui> Image<'ui> { impl<'ui> Image<'ui> {
pub fn new<S>(_: &Ui<'ui>, texture_id: usize, size: S) -> Self pub fn new<S>(_: &Ui<'ui>, texture_id: ImTexture, size: S) -> Self
where where
S: Into<ImVec2>, S: Into<ImVec2>,
{ {
@ -79,7 +98,7 @@ impl<'ui> Image<'ui> {
pub fn build(self) { pub fn build(self) {
unsafe { unsafe {
sys::igImage( sys::igImage(
self.texture_id as *mut c_void, self.texture_id.0 as *mut c_void,
self.size, self.size,
self.uv0, self.uv0,
self.uv1, self.uv1,
@ -108,19 +127,19 @@ impl<T> Textures<T> {
let id = self.next; let id = self.next;
self.textures.insert(id, texture); self.textures.insert(id, texture);
self.next += 1; self.next += 1;
id ImTexture(id)
} }
pub fn replace(&mut self, id: ImTexture, texture: T) { pub fn replace(&mut self, id: ImTexture, texture: T) {
assert!(self.textures.contains_key(&id)); assert!(self.textures.contains_key(&id.0));
self.textures.insert(id, texture); self.textures.insert(id.0, texture);
} }
pub fn remove(&mut self, id: ImTexture) { pub fn remove(&mut self, id: ImTexture) {
self.textures.remove(&id); self.textures.remove(&id.0);
} }
pub fn get(&self, id: ImTexture) -> Option<&T> { pub fn get(&self, id: ImTexture) -> Option<&T> {
self.textures.get(&id) self.textures.get(&id.0)
} }
} }

View File

@ -172,8 +172,8 @@ impl ImGui {
}) })
} }
} }
pub fn set_texture_id(&mut self, value: usize) { pub fn set_texture_id(&mut self, value: ImTexture) {
self.fonts().set_texture_id(value); self.fonts().set_texture_id(value.id());
} }
pub fn set_ini_filename(&mut self, value: Option<ImString>) { pub fn set_ini_filename(&mut self, value: Option<ImString>) {
{ {