Add simplest possible image support for gfx renderer

This commit is contained in:
Tad Hardesty 2018-09-10 00:40:02 -07:00
parent 4f080de586
commit 456258524e
3 changed files with 130 additions and 4 deletions

View File

@ -7,7 +7,9 @@ use gfx::memory::Bind;
use gfx::texture::{FilterMethod, SamplerInfo, WrapMode};
use gfx::traits::FactoryExt;
use gfx::{Bundle, CommandBuffer, Encoder, Factory, IntoIndexBuffer, Rect, Resources, Slice};
use imgui::{DrawList, FrameSize, ImDrawIdx, ImDrawVert, ImGui, Ui};
use imgui::{DrawList, FrameSize, ImDrawIdx, ImDrawVert, ImGui, Ui, ImTexture};
use std::collections::HashMap;
pub type RendererResult<T> = Result<T, RendererError>;
@ -94,9 +96,13 @@ impl Shaders {
}
}
pub type Texture<R> = (gfx::handle::ShaderResourceView<R, [f32; 4]>, gfx::handle::Sampler<R>);
pub struct Renderer<R: Resources> {
bundle: Bundle<R, pipe::Data<R>>,
index_buffer: Buffer<R, u16>,
textures: HashMap<usize, Texture<R>>,
next_texture: usize,
}
impl<R: Resources> Renderer<R> {
@ -131,9 +137,13 @@ impl<R: Resources> Renderer<R> {
&[handle.pixels],
)
})?;
// TODO: set texture id in imgui
let sampler =
factory.create_sampler(SamplerInfo::new(FilterMethod::Trilinear, WrapMode::Clamp));
let pair = (texture, sampler);
let mut textures = HashMap::new();
textures.insert(0, pair.clone());
imgui.set_texture_id(0);
let data = pipe::Data {
vertex_buffer: vertex_buffer,
matrix: [
@ -142,7 +152,7 @@ impl<R: Resources> Renderer<R> {
[0.0, 0.0, -1.0, 0.0],
[-1.0, 1.0, 0.0, 1.0],
],
tex: (texture, sampler),
tex: pair,
out: out,
scissor: Rect {
x: 0,
@ -161,11 +171,22 @@ impl<R: Resources> Renderer<R> {
Ok(Renderer {
bundle: Bundle::new(slice, pso, data),
index_buffer: index_buffer,
textures,
next_texture: 1,
})
}
pub fn update_render_target(&mut self, out: RenderTargetView<R, gfx::format::Rgba8>) {
self.bundle.data.out = out;
}
pub fn add_texture(&mut self, texture: Texture<R>) -> ImTexture {
let id = self.next_texture;
self.textures.insert(id, texture);
self.next_texture += 1;
id
}
pub fn render<'a, F: Factory<R>, C: CommandBuffer<R>>(
&mut self,
ui: Ui<'a>,
@ -214,7 +235,10 @@ impl<R: Resources> Renderer<R> {
self.bundle.slice.start = 0;
for cmd in draw_list.cmd_buffer {
// TODO: check cmd.texture_id
if let Some(tex) = self.textures.get(&(cmd.texture_id as usize)) {
// cloning handles is okay, since they're Arcs internally
self.bundle.data.tex = tex.clone();
}
self.bundle.slice.end = self.bundle.slice.start + cmd.elem_count;
self.bundle.data.scissor = Rect {

90
src/image.rs Normal file
View File

@ -0,0 +1,90 @@
use super::{ImVec2, ImVec4, Ui};
use std::marker::PhantomData;
use std::os::raw::c_void;
use sys;
pub type ImTexture = usize;
/// Represent an image about to be drawn.
/// See [`Ui::image`].
///
/// Create your image using the builder pattern then [`Image::build`] it.
pub struct Image<'ui> {
/// we use Result to allow postponing any construction errors to the build call
texture_id: ImTexture,
size: ImVec2,
uv0: ImVec2,
uv1: ImVec2,
tint_col: ImVec4,
border_col: ImVec4,
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui> Image<'ui> {
pub fn new<S>(_: &Ui<'ui>, texture_id: usize, size: S) -> Self
where
S: Into<ImVec2>,
{
const DEFAULT_UV0: ImVec2 = ImVec2 { x: 0.0, y: 0.0 };
const DEFAULT_UV1: ImVec2 = ImVec2 { x: 1.0, y: 1.0 };
const DEFAULT_TINT_COL: ImVec4 = ImVec4 {
x: 1.0,
y: 1.0,
z: 1.0,
w: 1.0,
};
const DEFAULT_BORDER_COL: ImVec4 = ImVec4 {
x: 0.0,
y: 0.0,
z: 0.0,
w: 0.0,
};
Image {
texture_id: texture_id,
size: size.into(),
uv0: DEFAULT_UV0,
uv1: DEFAULT_UV1,
tint_col: DEFAULT_TINT_COL,
border_col: DEFAULT_BORDER_COL,
_phantom: PhantomData,
}
}
/// Set size (default based on texture)
pub fn size<T: Into<ImVec2>>(mut self, size: T) -> Self {
self.size = size.into();
self
}
/// Set uv0 (default `[0.0, 0.0]`)
pub fn uv0<T: Into<ImVec2>>(mut self, uv0: T) -> Self {
self.uv0 = uv0.into();
self
}
/// Set uv1 (default `[1.0, 1.0]`)
pub fn uv1<T: Into<ImVec2>>(mut self, uv1: T) -> Self {
self.uv1 = uv1.into();
self
}
/// Set tint color (default: no tint color)
pub fn tint_col<T: Into<ImVec4>>(mut self, tint_col: T) -> Self {
self.tint_col = tint_col.into();
self
}
/// Set border color (default: no border)
pub fn border_col<T: Into<ImVec4>>(mut self, border_col: T) -> Self {
self.border_col = border_col.into();
self
}
/// Draw image where the cursor currently is
pub fn build(self) {
unsafe {
sys::igImage(
self.texture_id as *mut c_void,
self.size,
self.uv0,
self.uv1,
self.tint_col,
self.border_col,
);
}
}
}

View File

@ -18,6 +18,7 @@ pub use drag::{
DragInt4, DragIntRange2,
};
pub use fonts::{FontGlyphRange, ImFont, ImFontAtlas, ImFontConfig};
pub use image::{ImTexture, Image};
pub use input::{
InputFloat, InputFloat2, InputFloat3, InputFloat4, InputInt, InputInt2, InputInt3, InputInt4,
InputText, InputTextMultiline,
@ -45,6 +46,7 @@ mod child_frame;
mod color_editors;
mod drag;
mod fonts;
mod image;
mod input;
mod menus;
mod plothistogram;
@ -1301,6 +1303,16 @@ impl<'ui> Ui<'ui> {
}
}
// Image
impl<'ui> Ui<'ui> {
pub fn image<S>(&self, texture: ImTexture, size: S) -> Image
where
S: Into<ImVec2>,
{
Image::new(self, texture, size)
}
}
impl<'ui> Ui<'ui> {
/// Calculate the size required for a given text string.
///