Split ffi module into imgui-sys

This commit is contained in:
Joonas Javanainen 2015-08-23 09:56:13 +03:00
parent 3a550208c9
commit 545c80f309
12 changed files with 165 additions and 102 deletions

View File

@ -7,13 +7,11 @@ readme = "README.markdown"
homepage = "https://github.com/gekkio/imgui-rs"
repository = "https://github.com/gekkio/imgui-rs"
license = "MIT"
build = "build.rs"
[features]
default = ["glium"]
[dependencies]
bitflags = "0.3"
libc = "0.1"
[dependencies.glium]
@ -21,6 +19,10 @@ version = "0.8"
default-features = false
optional = true
[dependencies.imgui-sys]
path = "imgui-sys"
version = "0.0.2"
[dependencies.sdl2]
version = "0.7"
optional = true

View File

@ -1,13 +0,0 @@
extern crate gcc;
fn main() {
gcc::Config::new()
.cpp(true)
.file("third-party/cimgui/cimgui/cimgui.cpp")
.file("third-party/cimgui/cimgui/fontAtlas.cpp")
.file("third-party/cimgui/cimgui/drawList.cpp")
.file("third-party/cimgui/imgui/imgui.cpp")
.file("third-party/cimgui/imgui/imgui_demo.cpp")
.file("third-party/cimgui/imgui/imgui_draw.cpp")
.compile("libcimgui.a");
}

25
imgui-sys/Cargo.toml Normal file
View File

@ -0,0 +1,25 @@
[package]
name = "imgui-sys"
version = "0.0.2"
authors = ["Joonas Javanainen <joonas.javanainen@gmail.com>"]
description = "Raw ocornut/imgui bindings for Rust"
readme = "README.markdown"
homepage = "https://github.com/gekkio/imgui-rs"
repository = "https://github.com/gekkio/imgui-rs"
license = "MIT"
build = "build.rs"
[features]
default = ["glium"]
[dependencies]
bitflags = "0.3"
libc = "0.1"
[dependencies.glium]
version = "0.8"
default-features = false
optional = true
[build-dependencies]
gcc = "0.3"

13
imgui-sys/build.rs Normal file
View File

@ -0,0 +1,13 @@
extern crate gcc;
fn main() {
gcc::Config::new()
.cpp(true)
.file("../third-party/cimgui/cimgui/cimgui.cpp")
.file("../third-party/cimgui/cimgui/fontAtlas.cpp")
.file("../third-party/cimgui/cimgui/drawList.cpp")
.file("../third-party/cimgui/imgui/imgui.cpp")
.file("../third-party/cimgui/imgui/imgui_demo.cpp")
.file("../third-party/cimgui/imgui/imgui_draw.cpp")
.compile("libcimgui.a");
}

View File

@ -0,0 +1,26 @@
use glium::vertex::{Attribute, AttributeType};
use libc::c_float;
use std::mem;
unsafe impl Attribute for ImVec2 {
fn get_type() -> AttributeType { <(c_float, c_float) as Attribute>::get_type() }
}
unsafe impl Attribute for ImVec4 {
fn get_type() -> AttributeType {
<(c_float, c_float, c_float, c_float) as Attribute>::get_type()
}
}
impl Vertex for ImDrawVert {
fn build_bindings() -> VertexFormat {
unsafe {
let dummy: &ImDrawVert = mem::transmute(0usize);
Cow::Owned(vec![
("pos".into(), mem::transmute(&dummy.pos), <ImVec2 as Attribute>::get_type()),
("uv".into(), mem::transmute(&dummy.uv), <ImVec2 as Attribute>::get_type()),
("col".into(), mem::transmute(&dummy.col), AttributeType::U8U8U8U8)
])
}
}
}

View File

@ -1,6 +1,18 @@
#![allow(non_upper_case_globals)]
#[macro_use]
extern crate bitflags;
extern crate libc;
#[cfg(feature = "glium")]
#[macro_use]
extern crate glium;
#[cfg(feature = "glium")]
use glium::vertex::{Attribute, AttributeType, Vertex, VertexFormat};
use libc::*;
#[cfg(feature = "glium")]
use std::borrow::Cow;
use std::mem;
use std::slice;
@ -227,6 +239,11 @@ impl ImVec2 {
}
}
#[cfg(feature = "glium")]
unsafe impl Attribute for ImVec2 {
fn get_type() -> AttributeType { <(c_float, c_float) as Attribute>::get_type() }
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct ImVec4 {
@ -247,6 +264,13 @@ impl ImVec4 {
}
}
#[cfg(feature = "glium")]
unsafe impl Attribute for ImVec4 {
fn get_type() -> AttributeType {
<(c_float, c_float, c_float, c_float) as Attribute>::get_type()
}
}
#[repr(C)]
pub struct ImGuiStyle {
pub alpha: c_float,
@ -430,6 +454,20 @@ pub struct ImDrawVert {
pub col: ImU32
}
#[cfg(feature = "glium")]
impl Vertex for ImDrawVert {
fn build_bindings() -> VertexFormat {
unsafe {
let dummy: &ImDrawVert = mem::transmute(0usize);
Cow::Owned(vec![
("pos".into(), mem::transmute(&dummy.pos), <ImVec2 as Attribute>::get_type()),
("uv".into(), mem::transmute(&dummy.uv), <ImVec2 as Attribute>::get_type()),
("col".into(), mem::transmute(&dummy.col), AttributeType::U8U8U8U8)
])
}
}
}
#[repr(C)]
pub struct ImDrawChannel {
pub cmd_buffer: ImVector<ImDrawCmd>,

View File

@ -6,14 +6,11 @@ use glium::backend::{Context, Facade};
use glium::draw_parameters::{BlendingFunction, LinearBlendingFactor};
use glium::index::PrimitiveType;
use glium::texture::{ClientFormat, RawImage2d};
use glium::vertex::{Attribute, AttributeType, Vertex, VertexFormat};
use libc::c_float;
use std::borrow::Cow;
use std::fmt;
use std::mem;
use std::rc::Rc;
use super::{DrawList, Ui, ImDrawIdx, ImDrawVert, ImGui, ImVec2, ImVec4};
use super::{DrawList, Ui, ImDrawIdx, ImDrawVert, ImGui};
pub type RendererResult<T> = Result<T, RendererError>;
@ -69,29 +66,6 @@ impl From<DrawError> for RendererError {
}
}
unsafe impl Attribute for ImVec2 {
fn get_type() -> AttributeType { <(c_float, c_float) as Attribute>::get_type() }
}
unsafe impl Attribute for ImVec4 {
fn get_type() -> AttributeType {
<(c_float, c_float, c_float, c_float) as Attribute>::get_type()
}
}
impl Vertex for ImDrawVert {
fn build_bindings() -> VertexFormat {
unsafe {
let dummy: &ImDrawVert = mem::transmute(0usize);
Cow::Owned(vec![
("pos".into(), mem::transmute(&dummy.pos), <ImVec2 as Attribute>::get_type()),
("uv".into(), mem::transmute(&dummy.uv), <ImVec2 as Attribute>::get_type()),
("col".into(), mem::transmute(&dummy.col), AttributeType::U8U8U8U8)
])
}
}
}
pub struct Renderer {
ctx: Rc<Context>,
device_objects: DeviceObjects

View File

@ -1,10 +1,9 @@
#[macro_use]
extern crate bitflags;
#[cfg(feature = "glium")]
#[macro_use]
extern crate glium;
extern crate imgui_sys;
extern crate libc;
#[cfg(feature = "sdl2")]
@ -19,7 +18,7 @@ use std::ptr;
use std::slice;
use std::str;
pub use ffi::{
pub use imgui_sys::{
ImDrawIdx, ImDrawVert,
ImGuiSetCond,
ImGuiSetCond_Always, ImGuiSetCond_Once,
@ -36,7 +35,6 @@ pub use sliders::{SliderFloat, SliderInt};
pub use widgets::{CollapsingHeader};
pub use window::{Window};
pub mod ffi;
mod menus;
mod sliders;
mod widgets;
@ -93,26 +91,26 @@ pub struct TextureHandle<'a> {
pub fn get_version() -> &'static str {
unsafe {
let bytes = CStr::from_ptr(ffi::igGetVersion()).to_bytes();
let bytes = CStr::from_ptr(imgui_sys::igGetVersion()).to_bytes();
str::from_utf8_unchecked(bytes)
}
}
impl ImGui {
pub fn init() -> ImGui {
let io: &mut ffi::ImGuiIO = unsafe { mem::transmute(ffi::igGetIO()) };
let io: &mut imgui_sys::ImGuiIO = unsafe { mem::transmute(imgui_sys::igGetIO()) };
io.render_draw_lists_fn = Some(render_draw_lists);
ImGui
}
pub fn prepare_texture<'a, F, T>(&mut self, f: F) -> T where F: FnOnce(TextureHandle<'a>) -> T {
let io: &mut ffi::ImGuiIO = unsafe { mem::transmute(ffi::igGetIO()) };
let io: &mut imgui_sys::ImGuiIO = unsafe { mem::transmute(imgui_sys::igGetIO()) };
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;
unsafe {
ffi::ImFontAtlas_GetTexDataAsRGBA32(io.fonts, &mut pixels, &mut width, &mut height, &mut bytes_per_pixel);
imgui_sys::ImFontAtlas_GetTexDataAsRGBA32(io.fonts, &mut pixels, &mut width, &mut height, &mut bytes_per_pixel);
f(TextureHandle {
width: width as u32,
height: height as u32,
@ -121,32 +119,32 @@ impl ImGui {
}
}
pub fn draw_mouse_cursor(&mut self, value: bool) {
let io: &mut ffi::ImGuiIO = unsafe { mem::transmute(ffi::igGetIO()) };
let io: &mut imgui_sys::ImGuiIO = unsafe { mem::transmute(imgui_sys::igGetIO()) };
io.mouse_draw_cursor = value;
}
pub fn mouse_pos(&self) -> (f32, f32) {
let io: &mut ffi::ImGuiIO = unsafe { mem::transmute(ffi::igGetIO()) };
let io: &mut imgui_sys::ImGuiIO = unsafe { mem::transmute(imgui_sys::igGetIO()) };
(io.mouse_pos.x, io.mouse_pos.y)
}
pub fn set_mouse_pos(&mut self, x: f32, y: f32) {
let io: &mut ffi::ImGuiIO = unsafe { mem::transmute(ffi::igGetIO()) };
let io: &mut imgui_sys::ImGuiIO = unsafe { mem::transmute(imgui_sys::igGetIO()) };
io.mouse_pos.x = x;
io.mouse_pos.y = y;
}
pub fn set_mouse_down(&mut self, states: &[bool; 5]) {
let io: &mut ffi::ImGuiIO = unsafe { mem::transmute(ffi::igGetIO()) };
let io: &mut imgui_sys::ImGuiIO = unsafe { mem::transmute(imgui_sys::igGetIO()) };
io.mouse_down = *states;
}
pub fn get_time(&self) -> f32 { unsafe { ffi::igGetTime() } }
pub fn get_frame_count(&self) -> i32 { unsafe { ffi::igGetFrameCount() } }
pub fn get_time(&self) -> f32 { unsafe { imgui_sys::igGetTime() } }
pub fn get_frame_count(&self) -> i32 { unsafe { imgui_sys::igGetFrameCount() } }
pub fn frame<'ui, 'a: 'ui>(&'a mut self, width: u32, height: u32, delta_time: f32) -> Ui<'ui> {
unsafe {
let io: &mut ffi::ImGuiIO = mem::transmute(ffi::igGetIO());
let io: &mut imgui_sys::ImGuiIO = mem::transmute(imgui_sys::igGetIO());
io.display_size.x = width as c_float;
io.display_size.y = height as c_float;
io.delta_time = delta_time;
ffi::igNewFrame();
imgui_sys::igNewFrame();
}
Ui {
imgui: self
@ -157,7 +155,7 @@ impl ImGui {
impl Drop for ImGui {
fn drop(&mut self) {
unsafe {
ffi::igShutdown();
imgui_sys::igShutdown();
}
}
}
@ -166,7 +164,7 @@ impl Drop for ImGui {
impl ImGui {
pub fn update_mouse(&mut self, mouse: &::sdl2::mouse::MouseUtil) {
let (mouse_state, mouse_x, mouse_y) = mouse.get_mouse_state();
let io: &mut ffi::ImGuiIO = unsafe { mem::transmute(ffi::igGetIO()) };
let io: &mut imgui_sys::ImGuiIO = unsafe { mem::transmute(imgui_sys::igGetIO()) };
io.mouse_pos.x = mouse_x as f32;
io.mouse_pos.y = mouse_y as f32;
io.mouse_down = [
@ -180,9 +178,9 @@ impl ImGui {
}
pub struct DrawList<'a> {
pub cmd_buffer: &'a [ffi::ImDrawCmd],
pub idx_buffer: &'a [ffi::ImDrawIdx],
pub vtx_buffer: &'a [ffi::ImDrawVert]
pub cmd_buffer: &'a [imgui_sys::ImDrawCmd],
pub idx_buffer: &'a [imgui_sys::ImDrawIdx],
pub vtx_buffer: &'a [imgui_sys::ImDrawVert]
}
pub struct Ui<'ui> {
@ -200,8 +198,8 @@ impl<'ui> Ui<'ui> {
unsafe {
let mut im_draw_data = mem::zeroed();
RENDER_DRAW_LISTS_STATE.0 = &mut im_draw_data;
ffi::igRender();
RENDER_DRAW_LISTS_STATE.0 = 0 as *mut ffi::ImDrawData;
imgui_sys::igRender();
RENDER_DRAW_LISTS_STATE.0 = 0 as *mut imgui_sys::ImDrawData;
for &cmd_list in im_draw_data.cmd_lists() {
let draw_list =
@ -215,15 +213,15 @@ impl<'ui> Ui<'ui> {
}
Ok(())
}
pub fn show_user_guide(&self) { unsafe { ffi::igShowUserGuide() }; }
pub fn show_user_guide(&self) { unsafe { imgui_sys::igShowUserGuide() }; }
pub fn show_test_window(&self, opened: &mut bool) {
unsafe {
ffi::igShowTestWindow(opened);
imgui_sys::igShowTestWindow(opened);
}
}
pub fn show_metrics_window(&self, opened: &mut bool) {
unsafe {
ffi::igShowMetricsWindow(opened);
imgui_sys::igShowMetricsWindow(opened);
}
}
}
@ -235,18 +233,18 @@ impl<'ui> Ui<'ui> {
// Layout
impl<'ui> Ui<'ui> {
pub fn separator(&self) { unsafe { ffi::igSeparator() }; }
pub fn separator(&self) { unsafe { imgui_sys::igSeparator() }; }
pub fn same_line(&self, pos_x: f32) {
unsafe {
ffi::igSameLine(pos_x, -1.0f32)
imgui_sys::igSameLine(pos_x, -1.0f32)
}
}
pub fn same_line_spacing(&self, pos_x: f32, spacing_w: f32) {
unsafe {
ffi::igSameLine(pos_x, spacing_w)
imgui_sys::igSameLine(pos_x, spacing_w)
}
}
pub fn spacing(&self) { unsafe { ffi::igSpacing() }; }
pub fn spacing(&self) { unsafe { imgui_sys::igSpacing() }; }
}
// Widgets
@ -254,44 +252,44 @@ impl<'ui> Ui<'ui> {
pub fn text<'b>(&self, text: ImStr<'b>) {
// TODO: use igTextUnformatted
unsafe {
ffi::igText(fmt_ptr(), text.as_ptr());
imgui_sys::igText(fmt_ptr(), text.as_ptr());
}
}
pub fn text_colored<'b, A>(&self, col: A, text: ImStr<'b>) where A: Into<ImVec4> {
unsafe {
ffi::igTextColored(col.into(), fmt_ptr(), text.as_ptr());
imgui_sys::igTextColored(col.into(), fmt_ptr(), text.as_ptr());
}
}
pub fn text_disabled<'b>(&self, text: ImStr<'b>) {
unsafe {
ffi::igTextDisabled(fmt_ptr(), text.as_ptr());
imgui_sys::igTextDisabled(fmt_ptr(), text.as_ptr());
}
}
pub fn text_wrapped<'b>(&self, text: ImStr<'b>) {
unsafe {
ffi::igTextWrapped(fmt_ptr(), text.as_ptr());
imgui_sys::igTextWrapped(fmt_ptr(), text.as_ptr());
}
}
pub fn label_text<'b>(&self, label: ImStr<'b>, text: ImStr<'b>) {
unsafe {
ffi::igLabelText(label.as_ptr(), fmt_ptr(), text.as_ptr());
imgui_sys::igLabelText(label.as_ptr(), fmt_ptr(), text.as_ptr());
}
}
pub fn bullet(&self) {
unsafe {
ffi::igBullet();
imgui_sys::igBullet();
}
}
pub fn bullet_text<'b>(&self, text: ImStr<'b>) {
unsafe {
ffi::igBulletText(fmt_ptr(), text.as_ptr());
imgui_sys::igBulletText(fmt_ptr(), text.as_ptr());
}
}
pub fn collapsing_header<'p>(&self, label: ImStr<'p>) -> CollapsingHeader<'ui, 'p> {
CollapsingHeader::new(label)
}
pub fn checkbox<'p>(&self, label: ImStr<'p>, value: &'p mut bool) -> bool {
unsafe { ffi::igCheckbox(label.as_ptr(), value) }
unsafe { imgui_sys::igCheckbox(label.as_ptr(), value) }
}
}
@ -310,30 +308,30 @@ impl<'ui> Ui<'ui> {
// Widgets: Menus
impl<'ui> Ui<'ui> {
pub fn main_menu_bar<F>(&self, f: F) where F: FnOnce() {
let render = unsafe { ffi::igBeginMainMenuBar() };
let render = unsafe { imgui_sys::igBeginMainMenuBar() };
if render {
f();
unsafe { ffi::igEndMainMenuBar() };
unsafe { imgui_sys::igEndMainMenuBar() };
}
}
pub fn menu_bar<F>(&self, f: F) where F: FnOnce() {
let render = unsafe { ffi::igBeginMenuBar() };
let render = unsafe { imgui_sys::igBeginMenuBar() };
if render {
f();
unsafe { ffi::igEndMenuBar() };
unsafe { imgui_sys::igEndMenuBar() };
}
}
pub fn menu<'p>(&self, label: ImStr<'p>) -> Menu<'ui, 'p> { Menu::new(label) }
pub fn menu_item<'p>(&self, label: ImStr<'p>) -> MenuItem<'ui, 'p> { MenuItem::new(label) }
}
struct RenderDrawListsState(*mut ffi::ImDrawData);
struct RenderDrawListsState(*mut imgui_sys::ImDrawData);
unsafe impl Sync for RenderDrawListsState {}
static mut RENDER_DRAW_LISTS_STATE: RenderDrawListsState =
RenderDrawListsState(0 as *mut ffi::ImDrawData);
RenderDrawListsState(0 as *mut imgui_sys::ImDrawData);
extern "C" fn render_draw_lists(data: *mut ffi::ImDrawData) {
extern "C" fn render_draw_lists(data: *mut imgui_sys::ImDrawData) {
unsafe {
ptr::copy_nonoverlapping(data, RENDER_DRAW_LISTS_STATE.0, 1);
}

View File

@ -1,7 +1,7 @@
use imgui_sys;
use std::marker::PhantomData;
use std::ptr;
use super::ffi;
use super::{Ui, ImStr};
pub struct Menu<'ui, 'p> {
@ -26,10 +26,10 @@ impl<'ui, 'p> Menu<'ui, 'p> {
}
}
pub fn build<F: FnOnce()>(self, f: F) {
let render = unsafe { ffi::igBeginMenu(self.label.as_ptr(), self.enabled) };
let render = unsafe { imgui_sys::igBeginMenu(self.label.as_ptr(), self.enabled) };
if render {
f();
unsafe { ffi::igEndMenu() };
unsafe { imgui_sys::igEndMenu() };
}
}
}
@ -79,7 +79,7 @@ impl<'ui, 'p> MenuItem<'ui, 'p> {
let selected = self.selected.map(|x| x as *mut bool).unwrap_or(ptr::null_mut());
let enabled = self.enabled;
unsafe {
ffi::igMenuItemPtr(label, shortcut, selected, enabled)
imgui_sys::igMenuItemPtr(label, shortcut, selected, enabled)
}
}
}

View File

@ -1,6 +1,6 @@
use imgui_sys;
use std::marker::PhantomData;
use super::ffi;
use super::{Ui, ImStr};
// TODO: Consider using Range, even though it is half-open
@ -34,7 +34,7 @@ impl<'ui, 'p> SliderInt<'ui, 'p> {
}
pub fn build(self) -> bool {
unsafe {
ffi::igSliderInt(self.label.as_ptr(), self.value, self.min, self.max,
imgui_sys::igSliderInt(self.label.as_ptr(), self.value, self.min, self.max,
self.display_format.as_ptr()
)
}
@ -79,7 +79,7 @@ impl<'ui, 'p> SliderFloat<'ui, 'p> {
}
pub fn build(self) -> bool {
unsafe {
ffi::igSliderFloat(self.label.as_ptr(), self.value, self.min, self.max,
imgui_sys::igSliderFloat(self.label.as_ptr(), self.value, self.min, self.max,
self.display_format.as_ptr(),
self.power
)

View File

@ -1,7 +1,7 @@
use imgui_sys;
use std::marker::PhantomData;
use std::ptr;
use super::ffi;
use super::{Ui, ImStr};
pub struct CollapsingHeader<'ui, 'p> {
@ -45,7 +45,7 @@ impl<'ui, 'p> CollapsingHeader<'ui, 'p> {
}
pub fn build(self) -> bool {
unsafe {
ffi::igCollapsingHeader(
imgui_sys::igCollapsingHeader(
self.label.as_ptr(),
self.str_id.map(|x| x.as_ptr()).unwrap_or(ptr::null()),
self.display_frame,

View File

@ -1,7 +1,7 @@
use imgui_sys;
use std::marker::PhantomData;
use std::ptr;
use super::ffi;
use super::{
Ui,
ImGuiSetCond,
@ -162,12 +162,12 @@ impl<'ui, 'p> Window<'ui, 'p> {
pub fn build<F: FnOnce()>(self, f: F) {
let render = unsafe {
if !self.pos_cond.is_empty() {
ffi::igSetNextWindowPos(ImVec2::new(self.pos.0, self.pos.1), self.pos_cond);
imgui_sys::igSetNextWindowPos(ImVec2::new(self.pos.0, self.pos.1), self.pos_cond);
}
if !self.size_cond.is_empty() {
ffi::igSetNextWindowSize(ImVec2::new(self.size.0, self.size.1), self.size_cond);
imgui_sys::igSetNextWindowSize(ImVec2::new(self.size.0, self.size.1), self.size_cond);
}
ffi::igBegin2(self.name.as_ptr(),
imgui_sys::igBegin2(self.name.as_ptr(),
self.opened.map(|x| x as *mut bool).unwrap_or(ptr::null_mut()),
ImVec2::new(0.0, 0.0), self.bg_alpha, self.flags
)
@ -175,6 +175,6 @@ impl<'ui, 'p> Window<'ui, 'p> {
if render {
f();
}
unsafe { ffi::igEnd() };
unsafe { imgui_sys::igEnd() };
}
}