diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown new file mode 100644 index 0000000..41a7175 --- /dev/null +++ b/CHANGELOG.markdown @@ -0,0 +1,81 @@ +# Change Log + +## [Unreleased] + +### Added + +- Support for columns, combo, listbox + +### Changed + +- ImStr::as_ptr is now part of the public API + +## [0.0.8] - 2016-04-15 + +### Added + +- Add a change log + +### Changed + +- Upgrade to glium 0.14 + +## [0.0.7] - 2016-03-26 + +### Changed + +- Upgrade to imgui/cimgui 1.47 + +### Fixed + +- Fix Glium rendering error when more than one texture is used ([issue #17](https://github.com/Gekkio/imgui-rs/issues/17)) + +## [0.0.6] - 2016-01-12 + +### Changed + +- Relicensed to dual MIT/Apache-2.0 +- Upgrade to glium 0.13 +- Upgrade to imgui/cimgui 1.46 + +## [0.0.5] - 2015-11-30 + +### Changed + +- Upgrade to glium 0.12 +- Upgrade to libc 0.2 + +## [0.0.4] - 2015-10-26 + +### Changed + +- Upgrade to glium 0.10 +- Lots of other changes + +## [0.0.3] - 2015-09-27 + +### Changed + +- Upgrade to glium 0.9 +- Lots of other changes + +## [0.0.2] - 2015-08-31 + +### Changed + +- Lots of changes + +## 0.0.1 - 2015-08-20 + +### Added + +- Initial release with cimgui/imgui 1.44, glium 0.9 + +[Unreleased]: https://github.com/Gekkio/imgui-rs/compare/v0.0.8...HEAD +[0.0.8]: https://github.com/Gekkio/imgui-rs/compare/v0.0.7...v0.0.8 +[0.0.7]: https://github.com/Gekkio/imgui-rs/compare/v0.0.6...v0.0.7 +[0.0.6]: https://github.com/Gekkio/imgui-rs/compare/v0.0.5...v0.0.6 +[0.0.5]: https://github.com/Gekkio/imgui-rs/compare/v0.0.4...v0.0.5 +[0.0.4]: https://github.com/Gekkio/imgui-rs/compare/v0.0.3...v0.0.4 +[0.0.3]: https://github.com/Gekkio/imgui-rs/compare/v0.0.2...v0.0.3 +[0.0.2]: https://github.com/Gekkio/imgui-rs/compare/v0.0.1...v0.0.2 diff --git a/Cargo.toml b/Cargo.toml index 4980e7d..58b4769 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "imgui" -version = "0.0.7-pre" +version = "0.0.9-pre" authors = ["Joonas Javanainen "] description = "Experimental bindings to ocornut/imgui" readme = "README.markdown" @@ -15,13 +15,12 @@ default = ["glium"] libc = "0.2" [dependencies.glium] -version = "0.13" +version = "0.14" default-features = false optional = true [dependencies.imgui-sys] path = "imgui-sys" -version = "0.0.7" [build-dependencies] gcc = "0.3" @@ -30,6 +29,6 @@ gcc = "0.3" time = "0.1" [dev-dependencies.glium] -version = "0.13" +version = "0.14" features = ["glutin"] default-features = false diff --git a/README.markdown b/README.markdown index 65664a7..77473d9 100644 --- a/README.markdown +++ b/README.markdown @@ -24,7 +24,9 @@ ui.window(im_str!("Hello world")) * Low-level API (imgui-sys) * Renderer for easy integration with [Glium](https://github.com/tomaka/glium) projects (optional) * Parts of high-level API -* Not horrible way of defining and passing null-terminated UTF-8 to ImGui +* Not horrible way of defining and passing null-terminated UTF-8 to ImGui. + The macro `im_str!` needs to be used most of the time. For more + information and justification for this design, please see [issue #7](https://github.com/Gekkio/imgui-rs/issues/7) * Parts of imgui\_demo.cpp reimplemented in Rust as an API usage example (examples/test\_window\_impl.rs) ## Important but unimplemented things diff --git a/examples/support/mod.rs b/examples/support/mod.rs index a7a6e58..fe654c0 100644 --- a/examples/support/mod.rs +++ b/examples/support/mod.rs @@ -1,7 +1,7 @@ use glium::{DisplayBuild, Surface}; use glium::backend::glutin_backend::GlutinFacade; use glium::glutin; -use glium::glutin::{ElementState, Event, MouseButton, MouseScrollDelta, VirtualKeyCode}; +use glium::glutin::{ElementState, Event, MouseButton, MouseScrollDelta, VirtualKeyCode, TouchPhase}; use imgui::{ImGui, Ui, ImGuiKey}; use imgui::glium_renderer::Renderer; use time::SteadyTime; @@ -119,15 +119,17 @@ impl Support { _ => {}, } }, - Event::MouseMoved(pos) => self.mouse_pos = pos, + Event::MouseMoved(x, y) => self.mouse_pos = (x, y), Event::MouseInput(state, MouseButton::Left) => self.mouse_pressed.0 = state == ElementState::Pressed, Event::MouseInput(state, MouseButton::Right) => self.mouse_pressed.1 = state == ElementState::Pressed, Event::MouseInput(state, MouseButton::Middle) => self.mouse_pressed.2 = state == ElementState::Pressed, - Event::MouseWheel(MouseScrollDelta::LineDelta(_, y)) => self.mouse_wheel = y, - Event::MouseWheel(MouseScrollDelta::PixelDelta(_, y)) => self.mouse_wheel = y, + Event::MouseWheel(MouseScrollDelta::LineDelta(_, y), TouchPhase::Moved) => + self.mouse_wheel = y, + Event::MouseWheel(MouseScrollDelta::PixelDelta(_, y), TouchPhase::Moved) => + self.mouse_wheel = y, Event::ReceivedCharacter(c) => self.imgui.add_input_character(c), _ => () } diff --git a/examples/test_window_impl.rs b/examples/test_window_impl.rs index e2bcfb9..dcca1d7 100644 --- a/examples/test_window_impl.rs +++ b/examples/test_window_impl.rs @@ -313,12 +313,12 @@ fn show_test_window<'a>(ui: &Ui<'a>, state: &mut State, opened: &mut bool) { ui.separator(); ui.label_text(im_str!("label"), im_str!("Value")); ui.combo(im_str!("combo"), &mut state.item, &[im_str!("aaaa"), im_str!("bbbb"), - im_str!("cccc"), im_str!("dddd"), im_str!("eeee")]); + im_str!("cccc"), im_str!("dddd"), im_str!("eeee")], -1); let items = [ im_str!("AAAA"), im_str!("BBBB"), im_str!("CCCC"), im_str!("DDDD"), im_str!("EEEE"), im_str!("FFFF"), im_str!("GGGG"), im_str!("HHHH"), im_str!("IIII"), im_str!("JJJJ"), im_str!("KKKK")]; - ui.combo(im_str!("combo scroll"), &mut state.item2, &items); + ui.combo(im_str!("combo scroll"), &mut state.item2, &items, -1); ui.input_text(im_str!("input text"), &mut state.text).build(); ui.input_int(im_str!("input int"), &mut state.i0).build(); ui.input_float(im_str!("input float"), &mut state.f0) diff --git a/imgui-sys/Cargo.toml b/imgui-sys/Cargo.toml index 7ade8f2..9a378d9 100644 --- a/imgui-sys/Cargo.toml +++ b/imgui-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "imgui-sys" -version = "0.0.7-pre" +version = "0.0.9-pre" authors = ["Joonas Javanainen "] description = "Raw ocornut/imgui bindings for Rust" homepage = "https://github.com/gekkio/imgui-rs" @@ -12,11 +12,11 @@ build = "build.rs" default = ["glium"] [dependencies] -bitflags = "0.3" +bitflags = "0.5" libc = "0.2" [dependencies.glium] -version = "0.13" +version = "0.14" default-features = false optional = true diff --git a/imgui-sys/src/lib.rs b/imgui-sys/src/lib.rs index 839c898..4c615fe 100644 --- a/imgui-sys/src/lib.rs +++ b/imgui-sys/src/lib.rs @@ -114,7 +114,7 @@ pub const ImGuiKey_COUNT: usize = 19; bitflags!( #[repr(C)] - flags ImGuiAlign: c_int { + pub flags ImGuiAlign: ::libc::c_int { const ImGuiAlign_Left = 1 << 0, const ImGuiAlign_Center = 1 << 1, const ImGuiAlign_Right = 1 << 2, @@ -150,7 +150,7 @@ pub const ImGuiMouseCursor_COUNT: usize = 7; bitflags!( #[repr(C)] - flags ImGuiWindowFlags: c_int { + pub flags ImGuiWindowFlags: ::libc::c_int { const ImGuiWindowFlags_NoTitleBar = 1 << 0, const ImGuiWindowFlags_NoResize = 1 << 1, const ImGuiWindowFlags_NoMove = 1 << 2, @@ -186,7 +186,7 @@ impl ImGuiWindowFlags { bitflags!( #[repr(C)] - flags ImGuiSetCond: c_int { + pub flags ImGuiSetCond: ::libc::c_int { const ImGuiSetCond_Always = 1 << 0, const ImGuiSetCond_Once = 1 << 1, const ImGuiSetCond_FirstUseEver = 1 << 2, @@ -196,7 +196,7 @@ bitflags!( bitflags!( #[repr(C)] - flags ImGuiInputTextFlags: c_int { + pub flags ImGuiInputTextFlags: ::libc::c_int { const ImGuiInputTextFlags_CharsDecimal = 1 << 0, const ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, const ImGuiInputTextFlags_CharsUppercase = 1 << 2, @@ -227,7 +227,7 @@ impl ImGuiInputTextFlags { bitflags!( #[repr(C)] - flags ImGuiSelectableFlags: c_int { + pub flags ImGuiSelectableFlags: ::libc::c_int { const ImGuiSelectableFlags_DontClosePopups = 1 << 0, const ImGuiSelectableFlags_SpanAllColumns = 1 << 1 } diff --git a/src/glium_renderer.rs b/src/glium_renderer.rs index 2c932f7..2338b7d 100644 --- a/src/glium_renderer.rs +++ b/src/glium_renderer.rs @@ -1,10 +1,12 @@ use glium::{ index, program, texture, vertex, - Blend, DrawError, DrawParameters, IndexBuffer, Program, Rect, Surface, Texture2d, VertexBuffer + Blend, DrawError, DrawParameters, GlObject, IndexBuffer, Program, Rect, Surface, Texture2d, + VertexBuffer }; use glium::backend::{Context, Facade}; use glium::index::PrimitiveType; use glium::texture::{ClientFormat, RawImage2d}; +use libc::uintptr_t; use std::borrow::Cow; use std::fmt; use std::rc::Rc; @@ -80,7 +82,10 @@ impl Renderer { } pub fn render<'a, S: Surface>(&mut self, surface: &mut S, ui: Ui<'a>) -> RendererResult<()> { - ui.render(|draw_list| self.render_draw_list(surface, draw_list)) + let _ = self.ctx.insert_debug_marker("imgui-rs: starting rendering"); + let result = ui.render(|draw_list| self.render_draw_list(surface, draw_list)); + let _ = self.ctx.insert_debug_marker("imgui-rs: rendering finished"); + result } fn render_draw_list<'a, S: Surface>(&mut self, surface: &mut S, draw_list: DrawList<'a>) -> RendererResult<()> { @@ -88,18 +93,21 @@ impl Renderer { try!(self.device_objects.upload_index_buffer(&self.ctx, draw_list.idx_buffer)); let (width, height) = surface.get_dimensions(); + let matrix = [ + [ 2.0 / (width as f32), 0.0, 0.0, 0.0 ], + [ 0.0, 2.0 / -(height as f32), 0.0, 0.0 ], + [ 0.0, 0.0, -1.0, 0.0 ], + [ -1.0, 1.0, 0.0, 1.0 ] + ]; + let font_texture_id = self.device_objects.texture.get_id() as uintptr_t; let mut idx_start = 0; for cmd in draw_list.cmd_buffer { - let matrix = [ - [ 2.0 / (width as f32), 0.0, 0.0, 0.0 ], - [ 0.0, 2.0 / -(height as f32), 0.0, 0.0 ], - [ 0.0, 0.0, -1.0, 0.0 ], - [ -1.0, 1.0, 0.0, 1.0 ] - ]; + // We don't support custom textures...yet! + assert!(cmd.texture_id as uintptr_t == font_texture_id); let uniforms = uniform! { matrix: matrix, - texture: self.device_objects.texture.sampled() + tex: &self.device_objects.texture }; let draw_params = DrawParameters { blend: Blend::alpha_blending(), @@ -162,6 +170,7 @@ impl DeviceObjects { }; Texture2d::new(ctx, data) })); + im_gui.set_texture_id(texture.get_id() as uintptr_t); Ok(DeviceObjects { vertex_buffer: vertex_buffer, @@ -178,6 +187,9 @@ impl DeviceObjects { return Ok(()); } self.vertex_buffer = try!(VertexBuffer::dynamic(ctx, vtx_buffer)); + let _ = ctx.get_context().insert_debug_marker( + &format!("imgui-rs: resized vertex buffer to {} bytes", + self.vertex_buffer.get_size())); Ok(()) } pub fn upload_index_buffer(&mut self, ctx: &F, @@ -189,6 +201,9 @@ impl DeviceObjects { } self.index_buffer = try!(IndexBuffer::dynamic(ctx, PrimitiveType::TrianglesList, idx_buffer)); + let _ = ctx.get_context().insert_debug_marker( + &format!("imgui-rs: resized index buffer to {} bytes", + self.index_buffer.get_size())); Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index ef5a2ce..770228a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ extern crate imgui_sys; extern crate libc; -use libc::{c_char, c_float, c_int, c_uchar}; +use libc::{c_char, c_float, c_int, c_uchar, c_void, uintptr_t}; use std::borrow::Cow; use std::convert::From; use std::ffi::CStr; @@ -93,7 +93,7 @@ impl<'a> ImStr<'a> { bytes: Cow::Borrowed(bytes) } } - fn as_ptr(&self) -> *const c_char { self.bytes.as_ptr() as *const c_char } + pub fn as_ptr(&self) -> *const c_char { self.bytes.as_ptr() as *const c_char } } impl<'a> From<&'a str> for ImStr<'a> { @@ -162,6 +162,11 @@ impl ImGui { }) } } + pub fn set_texture_id(&mut self, value: uintptr_t) { + unsafe { + (*self.io_mut().fonts).tex_id = value as *mut c_void; + } + } pub fn set_ini_filename(&mut self, value: Option>) { { let io = self.io_mut(); @@ -400,6 +405,36 @@ impl<'ui> Ui<'ui> { } } pub fn spacing(&self) { unsafe { imgui_sys::igSpacing() }; } + + pub fn columns<'p>(&self, count: i32, id: ImStr<'p>, border: bool){ + unsafe { imgui_sys::igColumns(count, id.as_ptr(), border) } + } + + pub fn next_column(&self) { + unsafe { imgui_sys::igNextColumn() } + } + + pub fn get_column_index(&self) -> i32 { + unsafe { imgui_sys::igGetColumnIndex() } + } + + pub fn get_column_offset(&self, column_index: i32) -> f32 { + unsafe { imgui_sys::igGetColumnOffset(column_index) } + } + + pub fn set_column_offset(&self, column_index: i32, offset_x: f32) { + unsafe { imgui_sys::igSetColumnOffset(column_index, offset_x) } + } + + pub fn get_column_width(&self, column_index: i32) -> f32 { + unsafe { imgui_sys::igGetColumnWidth(column_index) } + } + + pub fn get_columns_count(&self) -> i32 { + unsafe { imgui_sys::igGetColumnsCount() } + } + + } // Widgets @@ -451,13 +486,6 @@ impl<'ui> Ui<'ui> { pub fn checkbox<'p>(&self, label: ImStr<'p>, value: &'p mut bool) -> bool { unsafe { imgui_sys::igCheckbox(label.as_ptr(), value) } } - pub fn combo<'p>(&self, label: ImStr<'p>, current_item: &'p mut i32, items: &'p[ImStr<'p>]) -> bool { - // TODO: the callback version could avoid allocating this Vec - let c_items : Vec<*const c_char> = items.iter().map(|s| s.as_ptr()).collect(); - unsafe { - imgui_sys::igCombo(label.as_ptr(), current_item, c_items.as_ptr(), c_items.len() as c_int, -1) - } - } } // Widgets: Input @@ -562,3 +590,41 @@ impl<'ui> Ui<'ui> { } } } + +//Widgets: Combos +impl<'ui> Ui<'ui> { + pub fn combo<'p>(&self, + label: ImStr<'p>, + current_item: &mut i32, + items: &'p [ImStr<'p>], + height_in_items: i32) + -> bool { + let items_inner : Vec<*const c_char> = items.into_iter().map(|item| item.as_ptr()).collect(); + unsafe { + imgui_sys::igCombo(label.as_ptr(), + current_item, + items_inner.as_ptr() as *mut *const c_char, + items_inner.len() as i32, + height_in_items) + } + } +} + +//Widgets: ListBox +impl<'ui> Ui<'ui> { + pub fn list_box<'p>(&self, + label: ImStr<'p>, + current_item: &mut i32, + items: &'p [ImStr<'p>], + height_in_items: i32) + -> bool{ + let items_inner : Vec<*const c_char> = items.into_iter().map(|item| item.as_ptr()).collect(); + unsafe{ + imgui_sys::igListBox(label.as_ptr(), + current_item, + items_inner.as_ptr() as *mut *const c_char, + items_inner.len() as i32, + height_in_items) + } + } +}