diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index 1dc9100..6d8f66c 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -4,7 +4,65 @@ ### Added -- `input_text_multiline` +- New things in imgui/cimgui 1.53.1 + - Style: Add `PopupRounding`, `FrameBorderSize`, `WindowBorderSize`, `PopupBorderSize`. + - DemoWindow: Add `no_close` state. + - Input: Add `no_undo_redo` method. + - *imgui-sys*: + - `igStyleColorsDark` and `igStyleColorsLight` + - DragDrop low level API + - `igGetFrameHeight` + - `igBeginCombo`, `igEndCombo` + - `igSetItemDefaultFocus` + - `igGetOverlayDrawList` and `igGetDrawListSharedData` + - `ImFontConfig_DefaultConstructor` + - `ImDrawList_AddImageRounded` +- Input: Add `read_only` and `password` methods. +- Various utility functions +- Support for changing the mouse cursor +- Custom font support +- Support for item grouping (`group` function) +- Custom drawing with draw list manipulation +- Drag widgets +- Input: Add `input_text_multiline` method + +### Changed + +- Upgrade to imgui/cimgui 1.53.1 + - Rename `Ui::show_test_window` to `Ui::show_demo_window`. Keep redirection. + - Rename `sys::igGetItemsLineHeightWithSpacing` to `sys::igGetFrameHeightWithSpacing`. + Keep redirection. + - Rename `ImGuiTreeNodeFlags::AllowOverlapMode` to `ImGuiTreeNodeFlags::AllowItemOverlap`. + `sys::igSetNextWindowContentSize()`. Keep redirection. + - Rename `sys::ImGuiTextBuffer_append()` helper to `appendf()`. + - Rename `ImGuiStyleVar::ChildWindowRounding` to `ImGuiStyleVar::ChildRounding`. + Keep redirection. + - Rename `StyleVar::ChildWindowRounding` to `StyleVar::ChildRounding`. + Keep redirection. + - Rename `ImGuiCol::ChildWindowBg` to `ImGuiCol::ChildBg`. + Keep redirection. + +### Deprecated + +- Various imgui-sys things that were deprecated in imgui/cimgui 1.53.1 + - Obsolete `sys::igIsRootWindowFocused()` in favor of using + `sys::igIsWindowFocused(ImGuiFocusedFlags::RootWindow)`. + - Obsolete `sys::igIsRootWindowOrAnyChildFocused()` in favor of using + `sys::igIsWindowFocused(ImGuiFocusedFlags::RootAndChildWindows)`. + - Obsolete `sys::igIsRootWindowOrAnyChildHovered()` in favor of using + `sys::igIsWindowHovered(ImGuiHoveredFlags::RootAndChildWindows)`. + - Obsolete `sys::SetNextWindowContentWidth()` in favor of using + - Obsolete `Window::show_borders`. Use `StyleVar` instead. + - Obsolete `ImGuiCol::ComboBg`. Use `PopupBg` instead. + +### Removed + +- Features that were removed in imgui/cimgui 1.53.1 + - Remove `anti_aliased: bool` final parameter of `sys::ImDrawList_AddPolyline` + and `sys::ImDrawList_AddConvexPolyFilled`. + - Remove `ImGuiWindowFlags::ShowBorders` window flag. Borders are now fully + set up in the ImGuiStyle structure. +- Various imgui-sys things that were deprecated in imgui/cimgui 1.52 ## [0.0.18] - 2017-12-23 diff --git a/imgui-examples/examples/hello_world.rs b/imgui-examples/examples/hello_world.rs index b5dddef..f35d58c 100644 --- a/imgui-examples/examples/hello_world.rs +++ b/imgui-examples/examples/hello_world.rs @@ -9,7 +9,7 @@ mod support; const CLEAR_COLOR: [f32; 4] = [1.0, 1.0, 1.0, 1.0]; -fn main() { support::run("hellow_world.rs".to_owned(), CLEAR_COLOR, hello_world); } +fn main() { support::run("hello_world.rs".to_owned(), CLEAR_COLOR, hello_world); } fn hello_world<'a>(ui: &Ui<'a>) -> bool { ui.window(im_str!("Hello world")) diff --git a/imgui-examples/examples/test_window.rs b/imgui-examples/examples/test_window.rs index 652b228..d111416 100644 --- a/imgui-examples/examples/test_window.rs +++ b/imgui-examples/examples/test_window.rs @@ -9,7 +9,7 @@ const CLEAR_COLOR: [f32; 4] = [0.2, 0.2, 0.2, 1.0]; fn main() { support::run("test_window.rs".to_owned(), CLEAR_COLOR, |ui| { let mut open = true; - ui.show_test_window(&mut open); + ui.show_demo_window(&mut open); open }); } diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs index 9a6ce24..342d13d 100644 --- a/imgui-examples/examples/test_window_impl.rs +++ b/imgui-examples/examples/test_window_impl.rs @@ -23,12 +23,12 @@ struct State { show_app_metrics: bool, show_app_about: bool, no_titlebar: bool, - no_border: bool, no_resize: bool, no_move: bool, no_scrollbar: bool, no_collapse: bool, no_menu: bool, + no_close: bool, wrap_width: f32, buf: ImString, item: i32, @@ -75,12 +75,12 @@ impl Default for State { show_app_metrics: false, show_app_about: false, no_titlebar: false, - no_border: true, no_resize: false, no_move: false, no_scrollbar: false, no_collapse: false, no_menu: false, + no_close: false, wrap_width: 200.0, buf: buf, item: 0, @@ -271,17 +271,18 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { ); } - ui.window(im_str!("ImGui Demo")) + let mut window = ui.window(im_str!("ImGui Demo")) .title_bar(!state.no_titlebar) - .show_borders(!state.no_border) .resizable(!state.no_resize) .movable(!state.no_move) .scroll_bar(!state.no_scrollbar) .collapsible(!state.no_collapse) .menu_bar(!state.no_menu) - .size((550.0, 680.0), ImGuiCond::FirstUseEver) - .opened(opened) - .build(|| { + .size((550.0, 680.0), ImGuiCond::FirstUseEver); + if !state.no_close { + window = window.opened(opened) + } + window.build(|| { ui.push_item_width(-140.0); ui.text(format!("dear imgui says hello. ({})", imgui::get_version())); ui.menu_bar(|| { @@ -348,15 +349,15 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { if ui.collapsing_header(im_str!("Window options")).build() { ui.checkbox(im_str!("No titlebar"), &mut state.no_titlebar); ui.same_line(150.0); - ui.checkbox(im_str!("No border"), &mut state.no_border); - ui.same_line(300.0); - ui.checkbox(im_str!("No resize"), &mut state.no_resize); - ui.checkbox(im_str!("No move"), &mut state.no_move); - ui.same_line(150.0); ui.checkbox(im_str!("No scrollbar"), &mut state.no_scrollbar); ui.same_line(300.0); - ui.checkbox(im_str!("No collapse"), &mut state.no_collapse); ui.checkbox(im_str!("No menu"), &mut state.no_menu); + ui.checkbox(im_str!("No move"), &mut state.no_move); + ui.same_line(150.0); + ui.checkbox(im_str!("No resize"), &mut state.no_resize); + ui.same_line(300.0); + ui.checkbox(im_str!("No collapse"), &mut state.no_collapse); + ui.checkbox(im_str!("No close"), &mut state.no_close); ui.tree_node(im_str!("Style")).build(|| { ui.show_default_style_editor() diff --git a/imgui-gfx-renderer/src/lib.rs b/imgui-gfx-renderer/src/lib.rs index be792bd..ccd32fd 100644 --- a/imgui-gfx-renderer/src/lib.rs +++ b/imgui-gfx-renderer/src/lib.rs @@ -180,8 +180,11 @@ impl Renderer { [-1.0, 1.0, 0.0, 1.0], ]; - ui.render(|ui, draw_list| { - self.render_draw_list(ui, factory, encoder, &draw_list) + ui.render(|ui, draw_data| { + for draw_list in &draw_data { + self.render_draw_list(ui, factory, encoder, &draw_list)?; + } + Ok(()) }) } fn render_draw_list<'a, F: Factory, C: CommandBuffer>( diff --git a/imgui-glium-renderer/src/lib.rs b/imgui-glium-renderer/src/lib.rs index b24af57..4a70fba 100644 --- a/imgui-glium-renderer/src/lib.rs +++ b/imgui-glium-renderer/src/lib.rs @@ -73,8 +73,11 @@ impl Renderer { 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 result = ui.render(|ui, draw_list| { - self.render_draw_list(surface, ui, &draw_list) + let result = ui.render(|ui, draw_data| { + for draw_list in draw_data.into_iter() { + self.render_draw_list(surface, ui, &draw_list)?; + } + Ok(()) }); let _ = self.ctx.insert_debug_marker("imgui-rs: rendering finished"); result diff --git a/imgui-sys/Cargo.toml b/imgui-sys/Cargo.toml index bbc0fe1..40488d7 100644 --- a/imgui-sys/Cargo.toml +++ b/imgui-sys/Cargo.toml @@ -13,6 +13,7 @@ build = "build.rs" travis-ci = { repository = "Gekkio/imgui-rs" } [dependencies] +libc = "0.2" bitflags = "1.0" glium = { version = "0.21", default-features = false, optional = true } gfx = { version = "0.17", optional = true } diff --git a/imgui-sys/src/lib.rs b/imgui-sys/src/lib.rs index 3d0f6a1..93c1c56 100644 --- a/imgui-sys/src/lib.rs +++ b/imgui-sys/src/lib.rs @@ -3,6 +3,8 @@ #[macro_use] extern crate bitflags; +extern crate libc; + #[cfg(feature = "gfx")] #[macro_use] extern crate gfx; @@ -13,7 +15,6 @@ extern crate glium; use std::convert::From; use std::mem; use std::os::raw::{c_char, c_float, c_int, c_short, c_uchar, c_uint, c_ushort, c_void}; -use std::ptr; use std::slice; #[cfg(feature = "gfx")] @@ -44,7 +45,7 @@ pub enum ImGuiCol { Text, TextDisabled, WindowBg, - ChildWindowBg, + ChildBg, PopupBg, Border, BorderShadow, @@ -59,7 +60,6 @@ pub enum ImGuiCol { ScrollbarGrab, ScrollbarGrabHovered, ScrollbarGrabActive, - ComboBg, CheckMark, SliderGrab, SliderGrabActive, @@ -84,15 +84,21 @@ pub enum ImGuiCol { PlotHistogramHovered, TextSelectedBg, ModalWindowDarkening, + DragDropTarget, } impl ImGuiCol { + #[deprecated(since = "0.0.19", note = "ComboBg has been merged with PopupBg. Please use PopupBg instead")] + pub const ComboBg: ImGuiCol = ImGuiCol::PopupBg; + #[deprecated(since = "0.0.19", note = "please use ChildBg instead")] + pub const ChildWindowBg: ImGuiCol = ImGuiCol::ChildBg; + pub fn values() -> &'static [ImGuiCol] { use ImGuiCol::*; static values: &'static [ImGuiCol] = &[ Text, TextDisabled, WindowBg, - ChildWindowBg, + ChildBg, PopupBg, Border, BorderShadow, @@ -107,7 +113,6 @@ impl ImGuiCol { ScrollbarGrab, ScrollbarGrabHovered, ScrollbarGrabActive, - ComboBg, CheckMark, SliderGrab, SliderGrabActive, @@ -132,6 +137,7 @@ impl ImGuiCol { PlotHistogramHovered, TextSelectedBg, ModalWindowDarkening, + DragDropTarget, ]; values } @@ -145,17 +151,27 @@ pub enum ImGuiStyleVar { Alpha, WindowPadding, WindowRounding, + WindowBorderSize, WindowMinSize, - ChildWindowRounding, + ChildRounding, + ChildBorderSize, + PopupRounding, + PopupBorderSize, FramePadding, FrameRounding, + FrameBorderSize, ItemSpacing, ItemInnerSpacing, IndentSpacing, GrabMinSize, ButtonTextAlign, } -pub const ImGuiStyleVar_COUNT: usize = 12; +pub const ImGuiStyleVar_COUNT: usize = 17; + +impl ImGuiStyleVar { + #[deprecated(since = "0.0.19", note = "please use ChildRounding instead")] + pub const ChildWindowRounding: ImGuiStyleVar = ImGuiStyleVar::ChildRounding; +} /// A key identifier (ImGui-side enum) #[repr(C)] @@ -235,7 +251,6 @@ bitflags!( const NoScrollWithMouse = 1 << 4; const NoCollapse = 1 << 5; const AlwaysAutoResize = 1 << 6; - const ShowBorders = 1 << 7; const NoSavedSettings = 1 << 8; const NoInputs = 1 << 9; const MenuBar = 1 << 10; @@ -245,6 +260,7 @@ bitflags!( const AlwaysVerticalScrollbar = 1 << 14; const AlwaysHorizontalScrollbar = 1 << 15; const AlwaysUseWindowPadding = 1 << 16; + const ResizeFromAnySide = 1 << 17; } ); @@ -279,6 +295,7 @@ bitflags!( const AlwaysInsertMode = 1 << 13; const ReadOnly = 1 << 14; const Password = 1 << 15; + const NoUndoRedo = 1 << 16; } ); @@ -298,7 +315,9 @@ bitflags!( pub struct ImGuiTreeNodeFlags: c_int { const Selected = 1; const Framed = 1 << 1; + #[deprecated(since = "0.0.19", note = "please use AllowItemOverlap instead")] const AllowOverlapMode = 1 << 2; + const AllowItemOverlap = 1 << 2; const NoTreePushOnOpen = 1 << 3; const NoAutoOpenOnLog = 1 << 4; const DefaultOpen = 1 << 5; @@ -312,16 +331,94 @@ bitflags!( } ); +bitflags!( + /// Flags for window focus check + #[repr(C)] + pub struct ImGuiFocusedFlags: c_int { + const ChildWindows = 1 << 0; + const RootWindow = 1 << 1; + const RootAndChildWindows = + ImGuiFocusedFlags::RootWindow.bits | ImGuiFocusedFlags::ChildWindows.bits; + } +); + bitflags!( /// Flags for hover checks #[repr(C)] pub struct ImGuiHoveredFlags: c_int { - const AllowWhenBlockedByPopup = 1; - const AllowWhenBlockedByActiveItem = 1 << 2; - const AllowWhenOverlapped = 1 << 3; + const ChildWindows = 1 << 0; + const RootWindow = 1 << 1; + const AllowWhenBlockedByPopup = 1 << 2; + const AllowWhenBlockedByActiveItem = 1 << 4; + const AllowWhenOverlapped = 1 << 5; const RectOnly = ImGuiHoveredFlags::AllowWhenBlockedByPopup.bits | ImGuiHoveredFlags::AllowWhenBlockedByActiveItem.bits | ImGuiHoveredFlags::AllowWhenOverlapped.bits; + const RootAndChildWindows = ImGuiFocusedFlags::RootWindow.bits + | ImGuiFocusedFlags::ChildWindows.bits; + } +); + +bitflags!( + /// Flags for igBeginCombo + #[repr(C)] + pub struct ImGuiComboFlags: c_int { + /// Align the popup toward the left by default + const PopupAlignLeft = 1 << 0; + /// Max ~4 items visible. + /// Tip: If you want your combo popup to be a specific size you can use + /// igSetNextWindowSizeConstraints() prior to calling igBeginCombo() + const HeightSmall = 1 << 1; + /// Max ~8 items visible (default) + const HeightRegular = 1 << 2; + /// Max ~20 items visible + const HeightLarge = 1 << 3; + /// As many fitting items as possible + const HeightLargest = 1 << 4; + const HeightMask = ImGuiComboFlags::HeightSmall.bits + | ImGuiComboFlags::HeightRegular.bits + | ImGuiComboFlags::HeightLarge.bits + | ImGuiComboFlags::HeightLargest.bits; + } +); + +bitflags!( + /// Flags for igBeginDragDropSource(), igAcceptDragDropPayload() + #[repr(C)] + pub struct ImGuiDragDropFlags: c_int { + // BeginDragDropSource() flags + /// By default, a successful call to igBeginDragDropSource opens a + /// tooltip so you can display a preview or description of the source + /// contents. This flag disable this behavior. + const SourceNoPreviewTooltip = 1 << 0; + /// By default, when dragging we clear data so that igIsItemHovered() + /// will return true, to avoid subsequent user code submitting tooltips. + /// This flag disable this behavior so you can still call + /// igIsItemHovered() on the source item. + const SourceNoDisableHover = 1 << 1; + /// Disable the behavior that allows to open tree nodes and collapsing + /// header by holding over them while dragging a source item. + const SourceNoHoldToOpenOthers = 1 << 2; + /// Allow items such as igText(), igImage() that have no unique + /// identifier to be used as drag source, by manufacturing a temporary + /// identifier based on their window-relative position. This is + /// extremely unusual within the dear imgui ecosystem and so we made it + /// explicit. + const SourceAllowNullID = 1 << 3; + /// External source (from outside of imgui), won't attempt to read + /// current item/window info. Will always return true. Only one Extern + /// source can be active simultaneously. + const SourceExtern = 1 << 4; + // AcceptDragDropPayload() flags + /// igAcceptDragDropPayload() will returns true even before the mouse + /// button is released. You can then call igIsDelivery() to test if the + /// payload needs to be delivered. + const AcceptBeforeDelivery = 1 << 10; + /// Do not draw the default highlight rectangle when hovering over target. + const AcceptNoDrawDefaultRect = 1 << 11; + /// For peeking ahead and inspecting the payload before delivery. + const AcceptPeekOnly = ImGuiDragDropFlags::AcceptBeforeDelivery.bits + | ImGuiDragDropFlags::AcceptNoDrawDefaultRect.bits; } ); @@ -331,8 +428,8 @@ bitflags!( pub struct ImDrawCornerFlags: c_int { const TopLeft = 1 << 0; const TopRight = 1 << 1; - const BotRight = 1 << 2; - const BotLeft = 1 << 3; + const BotLeft = 1 << 2; + const BotRight = 1 << 3; const Top = ImDrawCornerFlags::TopLeft.bits | ImDrawCornerFlags::TopRight.bits; const Bot = ImDrawCornerFlags::BotLeft.bits @@ -345,6 +442,14 @@ bitflags!( } ); +bitflags!( + #[repr(C)] + pub struct ImDrawListFlags: c_int { + const AntiAliasedLines = 1 << 0; + const AntiAliasedFill = 1 << 1; + } +); + pub type ImGuiTextEditCallback = Option< extern "C" fn(data: *mut ImGuiTextEditCallbackData) -> c_int, >; @@ -443,19 +548,29 @@ pub struct ImGuiStyle { pub alpha: c_float, /// Padding within a window pub window_padding: ImVec2, - /// Minimum window size - pub window_min_size: ImVec2, /// Radius of window corners rounding. Set to 0.0f to have rectangular windows pub window_rounding: c_float, + /// Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. + pub window_border_size: c_float, + /// Minimum window size + pub window_min_size: ImVec2, /// Alignment for title bar text. Defaults to (0.0f, 0.5f) for left-aligned, vertically centered pub window_title_align: ImVec2, /// Radius of child window corners rounding. Set to 0.0f to have rectangular child windows - pub child_window_rounding: c_float, + pub child_rounding: c_float, + /// Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested. + pub child_border_size: c_float, + /// Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows + pub popup_rounding: c_float, + /// Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested. + pub popup_border_size: c_float, /// Padding within a framed rectangle (used by most widgets) pub frame_padding: ImVec2, /// Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most /// widgets). pub frame_rounding: c_float, + /// Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested. + pub frame_border_size: c_float, /// Horizontal and vertical spacing between widgets/lines pub item_spacing: ImVec2, /// Horizontal and vertical spacing between within elements of a composed @@ -490,7 +605,7 @@ pub struct ImGuiStyle { /// Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. pub anti_aliased_lines: bool, /// Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) - pub anti_aliased_shapes: bool, + pub anti_aliased_fill: bool, /// Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more /// polygons), increase to reduce quality. pub curve_tessellation_tol: c_float, @@ -522,7 +637,8 @@ pub struct ImGuiIO { pub display_visible_min: ImVec2, pub display_visible_max: ImVec2, - pub osx_behaviors: bool, + pub opt_mac_osx_behaviors: bool, + pub opt_cursor_blink: bool, pub render_draw_lists_fn: Option, @@ -567,6 +683,7 @@ pub struct ImGuiIO { mouse_down_owned: [bool; 5], mouse_down_duration: [c_float; 5], mouse_down_duration_prev: [c_float; 5], + mouse_drag_max_distance_abs: [ImVec2; 5], mouse_drag_max_distance_sqr: [c_float; 5], keys_down_duration: [c_float; 512], keys_down_duration_prev: [c_float; 512], @@ -597,6 +714,28 @@ pub struct ImGuiTextFilter { pub count_grep: c_int, } +/// Data payload for Drag and Drop operations +#[repr(C)] +pub struct ImGuiPayload { + /// Data (copied and owned by dear imgui) + pub data: *const c_void, + /// Data size + pub data_size: c_int, + + /// Source item id + source_id: ImGuiID, + /// Source parent id (if available) + source_parent_id: ImGuiID, + /// Data timestamp + data_frame_count: c_int, + /// Data type tag (short user-supplied string) + data_type: [c_char; 8 + 1], + /// Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets) + preview: bool, + /// Set when AcceptDragDropPayload() was called and mouse button is released over the target item. + delivery: bool, +} + #[repr(C)] pub struct ImGuiTextBuffer { pub buf: ImVector, @@ -706,6 +845,8 @@ pub struct ImDrawList { pub idx_buffer: ImVector, pub vtx_buffer: ImVector, + flags: ImDrawListFlags, + data: *const ImDrawListSharedData, owner_name: *const c_char, vtx_current_idx: c_uint, vtx_write_ptr: *mut ImDrawVert, @@ -718,6 +859,20 @@ pub struct ImDrawList { channels: ImVector, } +#[repr(C)] +pub struct ImDrawListSharedData { + /// UV of white pixel in the atlas + tex_uv_white_pixel: ImVec2, + /// Current/default font (optional, for simplified AddText overload) + font: *mut ImFont, + /// Current/default font size (optional, for simplified AddText overload) + font_size: c_float, + curve_tessellation_tol: c_float, + /// Value for PushClipRectFullscreen() + clip_rect_fullscreen: ImVec4, + circle_vtx12: [ImVec2; 12], +} + /// All draw command lists required to render the frame #[repr(C)] pub struct ImDrawData { @@ -756,31 +911,6 @@ pub struct ImFontConfig { name: [c_char; 32], dst_font: *mut ImFont, } -impl ImFontConfig { - // This function only exists because cimgui does not provide a wrapper around - // `ImGuiConfig::ImGuiConfig()`. This code is based off that constructor. - pub fn new() -> ImFontConfig { - ImFontConfig { - font_data: ptr::null_mut(), - font_data_size: 0, - font_data_owned_by_atlas: true, - font_no: 0, - size_pixels: 0.0, - oversample_h: 3, - oversample_v: 1, - pixel_snap_h: false, - glyph_extra_spacing: ImVec2::zero(), - glyph_offset: ImVec2::zero(), - glyph_ranges: ptr::null(), - merge_mode: false, - rasterizer_flags: 0, - rasterizer_multiply: 1.0, - - name: [0; 32], - dst_font: ptr::null_mut(), - } - } -} #[repr(C)] #[derive(Copy, Clone, Debug, Default)] @@ -855,17 +985,26 @@ extern "C" { pub fn igGetDrawData() -> *mut ImDrawData; pub fn igNewFrame(); pub fn igRender(); + pub fn igEndFrame(); pub fn igShutdown(); } // Demo/Debug/Info extern "C" { - pub fn igShowTestWindow(opened: *mut bool); + pub fn igShowDemoWindow(opened: *mut bool); pub fn igShowMetricsWindow(opened: *mut bool); pub fn igShowStyleEditor(style: *mut ImGuiStyle); + pub fn igShowStyleSelector(label: *const c_char); + pub fn igShowFontSelector(label: *const c_char); pub fn igShowUserGuide(); } +#[allow(non_snake_case)] +#[deprecated(since = "0.0.19", note = "please use igShowDemoWindow instead")] +pub unsafe fn igShowTestWindow(opened: *mut bool) { + igShowDemoWindow(opened) +} + // Window extern "C" { pub fn igBegin(name: *const c_char, open: *mut bool, flags: ImGuiWindowFlags) -> bool; @@ -907,7 +1046,6 @@ extern "C" { custom_callback_data: *mut c_void, ); pub fn igSetNextWindowContentSize(size: ImVec2); - pub fn igSetNextWindowContentWidth(width: c_float); pub fn igSetNextWindowCollapsed(collapsed: bool, cond: ImGuiCond); pub fn igSetNextWindowFocus(); pub fn igSetWindowPos(pos: ImVec2, cond: ImGuiCond); @@ -927,18 +1065,18 @@ extern "C" { pub fn igSetScrollY(scroll_y: c_float); pub fn igSetScrollHere(center_y_ratio: c_float); pub fn igSetScrollFromPosY(pos_y: c_float, center_y_ratio: c_float); - pub fn igSetKeyboardFocusHere(offset: c_int); pub fn igSetStateStorage(tree: *mut ImGuiStorage); pub fn igGetStateStorage() -> *mut ImGuiStorage; } +/// Set next window content's width. +/// +/// Original non-deprecated version preserved last Y value set by +/// [`igSetNextWindowContentSize`]. #[allow(non_snake_case)] -#[deprecated(since = "0.0.18", note = "please use igSetNextWindowPos instead")] -pub unsafe fn igSetNextWindowPosCenter(cond: ImGuiCond) { - let io = igGetIO(); - let pos = ImVec2::new((*io).display_size.x * 0.5, (*io).display_size.y * 0.5); - let pivot = ImVec2::new(0.5, 0.5); - igSetNextWindowPos(pos, cond, pivot); +#[deprecated(since = "0.0.19", note = "please use igSetNextWindowContentSize instead")] +pub unsafe fn igSetNextWindowContentWidth(width: c_float) { + igSetNextWindowContentSize(ImVec2 { x: width, y: 0.0 }) } // Parameter stack (shared) @@ -996,12 +1134,15 @@ extern "C" { pub fn igAlignTextToFramePadding(); pub fn igGetTextLineHeight() -> c_float; pub fn igGetTextLineHeightWithSpacing() -> c_float; - pub fn igGetItemsLineHeightWithSpacing() -> c_float; + pub fn igGetFrameHeight() -> c_float; + pub fn igGetFrameHeightWithSpacing() -> c_float; } #[allow(non_snake_case)] -#[deprecated(since = "0.0.18", note = "please use igAlignTextToFramePadding instead")] -pub unsafe fn igAlignFirstTextHeightToWidgets() { igAlignTextToFramePadding(); } +#[deprecated(since = "0.0.19", note = "please use igGetFrameHeightWithSpacing instead")] +pub unsafe fn igGetItemsLineHeightWithSpacing() -> c_float { + igGetFrameHeightWithSpacing() +} // Columns extern "C" { @@ -1067,28 +1208,6 @@ extern "C" { pub fn igCheckboxFlags(label: *const c_char, flags: *mut c_uint, flags_value: c_uint) -> bool; pub fn igRadioButtonBool(label: *const c_char, active: bool) -> bool; pub fn igRadioButton(label: *const c_char, v: *mut c_int, v_button: c_int) -> bool; - pub fn igCombo( - label: *const c_char, - current_item: *mut c_int, - items: *const *const c_char, - items_count: c_int, - height_in_items: c_int, - ) -> bool; - pub fn igCombo2( - label: *const c_char, - current_item: *mut c_int, - items_separated_by_zeros: *const c_char, - height_in_items: c_int, - ) -> bool; - pub fn igCombo3( - label: *const c_char, - current_item: *mut c_int, - items_getter: extern "C" fn(data: *mut c_void, idx: c_int, out_text: *mut *const c_char) - -> bool, - data: *mut c_void, - items_count: c_int, - height_in_items: c_int, - ) -> bool; pub fn igPlotLines( label: *const c_char, values: *const c_float, @@ -1136,6 +1255,37 @@ extern "C" { pub fn igProgressBar(fraction: c_float, size_arg: *const ImVec2, overlay: *const c_char); } +// Combo +extern "C" { + pub fn igBeginCombo( + label: *const c_char, + preview_value: *const c_char, + flags: ImGuiComboFlags, + ) -> bool; + pub fn igEndCombo(); + pub fn igCombo( + label: *const c_char, + current_item: *mut c_int, + items: *const *const c_char, + items_count: c_int, + height_in_items: c_int, + ) -> bool; + pub fn igCombo2( + label: *const c_char, + current_item: *mut c_int, + items_separated_by_zeros: *const c_char, + height_in_items: c_int, + ) -> bool; + pub fn igCombo3( + label: *const c_char, + current_item: *mut c_int, + items_getter: extern "C" fn(data: *mut c_void, idx: c_int, out_text: *mut *const c_char) -> bool, + data: *mut c_void, + items_count: c_int, + height_in_items: c_int, + ) -> bool; +} + // Widgets: Color Editor/Picker extern "C" { pub fn igColorEdit3( @@ -1564,6 +1714,24 @@ extern "C" { pub fn igLogText(fmt: *const c_char, ...); } +// DragDrop +extern "C" { + /// Call when current ID is active. + /// + /// When this returns true you need to: + /// + /// 1. call [`igSetDragDropPayload`] exactly once, + /// 2. you may render the payload visual/description, + /// 3. pcall [`igEndDragDropSource`] + pub fn igBeginDragDropSource(flags: ImGuiDragDropFlags, mouse_button: c_int) -> bool; + /// Use 'cond' to choose to submit payload on drag start or every frame + pub fn igSetDragDropPayload(type_: *const c_char, data: *const c_void, size: libc::size_t, cond: ImGuiCond) -> bool; + pub fn igEndDragDropSource(); + pub fn igBeginDragDropTarget() -> bool; + pub fn igAcceptDragDropPayload(type_: *const c_char, flags: ImGuiDragDropFlags) -> *const ImGuiPayload; + pub fn igEndDragDropTarget(); +} + // Clipping extern "C" { pub fn igPushClipRect( @@ -1577,6 +1745,14 @@ extern "C" { // Styles extern "C" { pub fn igStyleColorsClassic(dst: *mut ImGuiStyle); + pub fn igStyleColorsDark(dst: *mut ImGuiStyle); + pub fn igStyleColorsLight(dst: *mut ImGuiStyle); +} + +// Focus +extern "C" { + pub fn igSetItemDefaultFocus(); + pub fn igSetKeyboardFocusHere(offset: c_int); } // Utilities @@ -1591,11 +1767,8 @@ extern "C" { pub fn igGetItemRectMax(out: *mut ImVec2); pub fn igGetItemRectSize(out: *mut ImVec2); pub fn igSetItemAllowOverlap(); - pub fn igIsWindowFocused() -> bool; + pub fn igIsWindowFocused(flags: ImGuiFocusedFlags) -> bool; pub fn igIsWindowHovered(flags: ImGuiHoveredFlags) -> bool; - pub fn igIsRootWindowFocused() -> bool; - pub fn igIsRootWindowOrAnyChildFocused() -> bool; - pub fn igIsRootWindowOrAnyChildHovered(flags: ImGuiHoveredFlags) -> bool; pub fn igIsAnyWindowHovered() -> bool; pub fn igIsRectVisible(item_size: ImVec2) -> bool; pub fn igIsRectVisible2(rect_min: *const ImVec2, rect_max: *const ImVec2) -> bool; @@ -1645,6 +1818,28 @@ extern "C" { ); } +#[allow(non_snake_case)] +#[deprecated(since = "0.0.19", note = "please use igIsWindowFocused(ImGuiFocusedFlags::RootWindow) instead")] +pub unsafe fn igIsRootWindowFocused() -> bool { + igIsWindowFocused(ImGuiFocusedFlags::RootWindow) +} +#[allow(non_snake_case)] +#[deprecated(since = "0.0.19", note = "please use igIsWindowFocused(ImGuiFocusedFlags::RootAndChildWindows) instead")] +pub unsafe fn igIsRootWindowOrAnyChildFocused() -> bool { + igIsWindowFocused(ImGuiFocusedFlags::RootAndChildWindows) +} +#[allow(non_snake_case)] +#[deprecated(since = "0.0.19", note = "please use igIsWindowFocused(ImGuiFocusedFlags::RootAndChildWindows) instead")] +pub unsafe fn igIsRootWindowOrAnyChildHovered(_flags: ImGuiHoveredFlags) -> bool { + igIsWindowHovered(ImGuiHoveredFlags::RootAndChildWindows) +} + +// DrawList +extern "C" { + pub fn igGetOverlayDrawList() -> *mut ImDrawList; + pub fn igGetDrawListSharedData() -> *mut ImDrawListSharedData; +} + // Inputs extern "C" { pub fn igGetKeyIndex(imgui_key: ImGuiKey) -> c_int; @@ -1669,18 +1864,6 @@ extern "C" { pub fn igCaptureMouseFromApp(capture: bool); } -#[allow(non_snake_case)] -#[deprecated(since = "0.0.18", note = "please use igIsItemHovered instead")] -pub unsafe fn igIsItemRectHovered() -> bool { igIsItemHovered(ImGuiHoveredFlags::RectOnly) } -#[allow(non_snake_case)] -#[deprecated(since = "0.0.18", note = "please use igIsWindowHovered instead")] -pub unsafe fn igIsWindowRectHovered() -> bool { - igIsWindowHovered( - ImGuiHoveredFlags::AllowWhenBlockedByPopup | ImGuiHoveredFlags::AllowWhenBlockedByActiveItem, - ) -} - - // Helpers functions to access functions pointers in ImGui::GetIO() extern "C" { pub fn igMemAlloc(sz: usize) -> *mut c_void; @@ -1701,6 +1884,10 @@ extern "C" { pub fn igSetCurrentContext(ctx: *mut ImGuiContext); } +extern "C" { + pub fn ImFontConfig_DefaultConstructor(config: *mut ImFontConfig); +} + // ImGuiIO extern "C" { pub fn ImGuiIO_AddInputCharacter(c: c_ushort); @@ -1739,7 +1926,7 @@ extern "C" { pub fn ImGuiTextBuffer_empty(buffer: *mut ImGuiTextBuffer) -> bool; pub fn ImGuiTextBuffer_clear(buffer: *mut ImGuiTextBuffer); pub fn ImGuiTextBuffer_c_str(buffer: *const ImGuiTextBuffer) -> *const c_char; - pub fn ImGuiTextBuffer_append(buffer: *const ImGuiTextBuffer, fmt: *const c_char, ...); + pub fn ImGuiTextBuffer_appendf(buffer: *const ImGuiTextBuffer, fmt: *const c_char, ...); // pub fn ImGuiTextBuffer_appendv( // buffer: *const ImGuiTextBuffer, // fmt: *const c_char, @@ -1967,6 +2154,17 @@ extern "C" { uv_d: ImVec2, col: ImU32, ); + pub fn ImDrawList_AddImageRounded( + list: *mut ImDrawList, + user_texture_id: ImTextureID, + a: ImVec2, + b: ImVec2, + uv_a: ImVec2, + uv_b: ImVec2, + col: ImU32, + rounding: c_float, + rounding_corners: c_int, + ); pub fn ImDrawList_AddPolyLine( list: *mut ImDrawList, points: *const ImVec2, @@ -1974,14 +2172,12 @@ extern "C" { col: ImU32, closed: bool, thickness: c_float, - anti_aliased: bool, ); pub fn ImDrawList_AddConvexPolyFilled( list: *mut ImDrawList, points: *const ImVec2, num_points: c_int, col: ImU32, - anti_aliased: bool, ); pub fn ImDrawList_AddBezierCurve( list: *mut ImDrawList, @@ -2183,6 +2379,7 @@ extern "C" { pub fn ImFont_SetFallbackChar(font: *mut ImFont, c: ImWchar); pub fn ImFont_GetCharAdvance(font: *const ImFont, c: ImWchar) -> c_float; pub fn ImFont_IsLoaded(font: *const ImFont) -> bool; + pub fn ImFont_GetDebugName(font: *const ImFont) -> *const c_char; pub fn ImFont_CalcTextSizeA( font: *const ImFont, out: *mut ImVec2, @@ -2222,15 +2419,6 @@ extern "C" { ); } -#[allow(non_snake_case)] -#[deprecated(since = "0.0.18", note = "please use ImFont_ClearOutputData instead")] -pub unsafe fn ImFont_Clear(font: *mut ImFont) { ImFont_ClearOutputData(font); } -#[allow(non_snake_case)] -#[deprecated(since = "0.0.18", note = "please use ImFont_GetFallbackChar instead")] -pub unsafe fn ImFont_GetFallbackXAdvance(font: *const ImFont) -> c_float { - ImFont_GetFallbackAdvanceX(font) -} - // ImFont::Glyph extern "C" { pub fn ImFont_Glyphs_size(font: *const ImFont) -> c_int; @@ -2256,12 +2444,15 @@ fn test_default_style() { let style = unsafe { &*igGetStyle() }; assert_eq!(style.alpha, 1.0); assert_eq!(style.window_padding, ImVec2::new(8.0, 8.0)); + assert_eq!(style.window_rounding, 7.0); + assert_eq!(style.window_border_size, 0.0); assert_eq!(style.window_min_size, ImVec2::new(32.0, 32.0)); - assert_eq!(style.window_rounding, 9.0); assert_eq!(style.window_title_align, ImVec2::new(0.0, 0.5)); - assert_eq!(style.child_window_rounding, 0.0); + assert_eq!(style.popup_rounding, 0.0); + assert_eq!(style.popup_border_size, 1.0); assert_eq!(style.frame_padding, ImVec2::new(4.0, 3.0)); assert_eq!(style.frame_rounding, 0.0); + assert_eq!(style.frame_border_size, 0.0); assert_eq!(style.item_spacing, ImVec2::new(8.0, 4.0)); assert_eq!(style.item_inner_spacing, ImVec2::new(4.0, 4.0)); assert_eq!(style.touch_extra_padding, ImVec2::new(0.0, 0.0)); @@ -2275,6 +2466,6 @@ fn test_default_style() { assert_eq!(style.display_window_padding, ImVec2::new(22.0, 22.0)); assert_eq!(style.display_safe_area_padding, ImVec2::new(4.0, 4.0)); assert_eq!(style.anti_aliased_lines, true); - assert_eq!(style.anti_aliased_shapes, true); + assert_eq!(style.anti_aliased_fill, true); assert_eq!(style.curve_tessellation_tol, 1.25); } diff --git a/imgui-sys/third-party/cimgui b/imgui-sys/third-party/cimgui index 5112189..0781f92 160000 --- a/imgui-sys/third-party/cimgui +++ b/imgui-sys/third-party/cimgui @@ -1 +1 @@ -Subproject commit 511218914b6dde6d5e52c0d98454ead3369eb38d +Subproject commit 0781f921354a3f7a9eefd7aaab557a89cb14baea diff --git a/src/child_frame.rs b/src/child_frame.rs index b14f03a..aa1a0fd 100644 --- a/src/child_frame.rs +++ b/src/child_frame.rs @@ -7,6 +7,7 @@ use super::{ImStr, ImVec2, ImGuiWindowFlags, Ui}; pub struct ChildFrame<'ui, 'p> { name: &'p ImStr, size: ImVec2, + border: bool, flags: ImGuiWindowFlags, _phantom: PhantomData<&'ui Ui<'ui>>, } @@ -16,6 +17,7 @@ impl<'ui, 'p> ChildFrame<'ui, 'p> { ChildFrame { name: name, size: size.into(), + border: false, flags: ImGuiWindowFlags::empty(), _phantom: PhantomData, } @@ -47,7 +49,7 @@ impl<'ui, 'p> ChildFrame<'ui, 'p> { } #[inline] pub fn show_borders(mut self, value: bool) -> Self { - self.flags.set(ImGuiWindowFlags::ShowBorders, value); + self.border = value; self } #[inline] @@ -103,12 +105,8 @@ impl<'ui, 'p> ChildFrame<'ui, 'p> { self } pub fn build(self, f: F) { - // See issue for history. - // https://github.com/Gekkio/imgui-rs/pull/58 - let show_border = false; - let render_child_frame = - unsafe { sys::igBeginChild(self.name.as_ptr(), self.size, show_border, self.flags) }; + unsafe { sys::igBeginChild(self.name.as_ptr(), self.size, self.border, self.flags) }; if render_child_frame { f(); } diff --git a/src/fonts.rs b/src/fonts.rs index e5c0aae..a3023b7 100644 --- a/src/fonts.rs +++ b/src/fonts.rs @@ -156,7 +156,11 @@ impl ImFontConfig { } fn make_config(self) -> sys::ImFontConfig { - let mut config = sys::ImFontConfig::new(); + let mut config = unsafe { + let mut config = mem::uninitialized(); + sys::ImFontConfig_DefaultConstructor(&mut config); + config + }; config.size_pixels = self.size_pixels; config.oversample_h = self.oversample_h as c_int; config.oversample_v = self.oversample_v as c_int; diff --git a/src/input.rs b/src/input.rs index b1e6627..9e29460 100644 --- a/src/input.rs +++ b/src/input.rs @@ -89,6 +89,24 @@ macro_rules! impl_text_flags { self.flags.set(ImGuiInputTextFlags::AlwaysInsertMode, value); self } + + #[inline] + pub fn read_only(mut self, value: bool) -> Self { + self.flags.set(ImGuiInputTextFlags::ReadOnly, value); + self + } + + #[inline] + pub fn password(mut self, value: bool) -> Self { + self.flags.set(ImGuiInputTextFlags::Password, value); + self + } + + #[inline] + pub fn no_undo_redo(mut self, value: bool) -> Self { + self.flags.set(ImGuiInputTextFlags::NoUndoRedo, value); + self + } } } diff --git a/src/lib.rs b/src/lib.rs index 01a30d1..046782c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ pub extern crate imgui_sys as sys; use std::ffi::CStr; use std::mem; -use std::os::raw::{c_char, c_float, c_int, c_uchar}; +use std::os::raw::{c_char, c_float, c_int, c_uchar, c_void}; use std::ptr; use std::slice; use std::str; @@ -219,6 +219,11 @@ impl ImGui { let io = self.io_mut(); io.mouse_wheel = value; } + /// Get mouse wheel delta + pub fn mouse_wheel(&self) -> f32 { + let io = self.io(); + io.mouse_wheel + } /// Set to `true` to have ImGui draw the cursor in software. /// If `false`, the OS cursor is used (default to `false`). pub fn set_mouse_draw_cursor(&mut self, value: bool) { @@ -263,6 +268,18 @@ impl ImGui { sys::igIsMouseClicked(button as c_int, false) } } + /// Returns `true` if the `button` provided as argument is being double-clicked. + pub fn is_mouse_double_clicked(&self, button: ImMouseButton) -> bool { + unsafe { + sys::igIsMouseDoubleClicked(button as c_int) + } + } + /// Returns `true` if the `button` provided as argument was released + pub fn is_mouse_released(&self, button: ImMouseButton) -> bool { + unsafe { + sys::igIsMouseReleased(button as c_int) + } + } pub fn key_ctrl(&self) -> bool { let io = self.io(); io.key_ctrl @@ -299,6 +316,35 @@ impl ImGui { let io = self.io_mut(); io.key_map[key as usize] = mapping as i32; } + /// Map [`ImGuiKey`] values into user's key index + pub fn get_key_index(&self, key: ImGuiKey) -> usize { + unsafe { sys::igGetKeyIndex(key) as usize } + } + /// Return whether specific key is being held + /// + /// # Example + /// + /// ```rust + /// use imgui::{ImGuiKey, Ui}; + /// + /// fn test(ui: &Ui) { + /// let delete_key_index = ui.imgui().get_key_index(ImGuiKey::Delete); + /// if ui.imgui().is_key_down(delete_key_index) { + /// println!("Delete is being held!"); + /// } + /// } + /// ``` + pub fn is_key_down(&self, user_key_index: usize) -> bool { + unsafe { sys::igIsKeyDown(user_key_index as c_int) } + } + /// Return whether specific key was pressed + pub fn is_key_pressed(&self, user_key_index: usize) -> bool { + unsafe { sys::igIsKeyPressed(user_key_index as c_int, true) } + } + /// Return whether specific key was released + pub fn is_key_released(&self, user_key_index: usize) -> bool { + unsafe { sys::igIsKeyReleased(user_key_index as c_int) } + } pub fn add_input_character(&mut self, character: char) { let mut buf = [0; 5]; character.encode_utf8(&mut buf); @@ -350,6 +396,68 @@ impl Drop for ImGui { static mut CURRENT_UI: Option> = None; +pub struct DrawData<'a> { + raw: &'a mut sys::ImDrawData, +} + +impl<'a> DrawData<'a> { + pub fn is_valid(&self) -> bool { + self.raw.valid + } + pub fn draw_list_count(&self) -> usize { + self.raw.cmd_lists_count as usize + } + pub fn total_vtx_count(&self) -> usize { + self.raw.total_vtx_count as usize + } + pub fn total_idx_count(&self) -> usize { + self.raw.total_idx_count as usize + } + pub fn deindex_all_buffers(&mut self) { + unsafe { + sys::ImDrawData_DeIndexAllBuffers(self.raw); + } + } + pub fn scale_clip_rects>(&mut self, sc: S) { + unsafe { + sys::ImDrawData_ScaleClipRects(self.raw, sc.into()); + } + } +} + +impl<'a> IntoIterator for &'a DrawData<'a> { + type Item = DrawList<'a>; + type IntoIter = DrawListIterator<'a>; + + fn into_iter(self) -> Self::IntoIter { + unsafe { + DrawListIterator { + iter: self.raw.cmd_lists().iter(), + } + } + } +} + +pub struct DrawListIterator<'a> { + iter: std::slice::Iter<'a, *const sys::ImDrawList>, +} + +impl<'a> Iterator for DrawListIterator<'a> { + type Item = DrawList<'a>; + + fn next(&mut self) -> Option { + self.iter.next().map(|&ptr| { + unsafe { + DrawList { + cmd_buffer: (*ptr).cmd_buffer.as_slice(), + idx_buffer: (*ptr).idx_buffer.as_slice(), + vtx_buffer: (*ptr).vtx_buffer.as_slice(), + } + } + }) + } +} + pub struct DrawList<'a> { pub cmd_buffer: &'a [sys::ImDrawCmd], pub idx_buffer: &'a [sys::ImDrawIdx], @@ -394,22 +502,17 @@ impl<'ui> Ui<'ui> { let io = self.imgui.io(); io.metrics_active_windows } - pub fn render(self, mut f: F) -> Result<(), E> + pub fn render(self, f: F) -> Result<(), E> where - F: FnMut(&Ui, DrawList) -> Result<(), E>, + F: FnOnce(&Ui, DrawData) -> Result<(), E>, { unsafe { sys::igRender(); - let draw_data = sys::igGetDrawData(); - for &cmd_list in (*draw_data).cmd_lists() { - let draw_list = DrawList { - cmd_buffer: (*cmd_list).cmd_buffer.as_slice(), - idx_buffer: (*cmd_list).idx_buffer.as_slice(), - vtx_buffer: (*cmd_list).vtx_buffer.as_slice(), - }; - try!(f(&self, draw_list)); - } + let draw_data = DrawData { + raw: &mut *sys::igGetDrawData(), + }; + f(&self, draw_data)?; CURRENT_UI = None; } Ok(()) @@ -421,9 +524,13 @@ impl<'ui> Ui<'ui> { sys::igShowStyleEditor(style as *mut ImGuiStyle); } } + #[deprecated(since = "0.0.19", note = "please use show_demo_window instead")] pub fn show_test_window(&self, opened: &mut bool) { + self.show_demo_window(opened) + } + pub fn show_demo_window(&self, opened: &mut bool) { unsafe { - sys::igShowTestWindow(opened); + sys::igShowDemoWindow(opened); } } pub fn show_metrics_window(&self, opened: &mut bool) { @@ -553,10 +660,50 @@ impl<'ui> Ui<'ui> { } } +pub enum ImId<'a> { + Int(i32), + Str(&'a str), + Ptr(*const c_void), +} + +impl From for ImId<'static> { + fn from(i: i32) -> Self { ImId::Int(i) } +} + +impl<'a, T: ?Sized + AsRef> From<&'a T> for ImId<'a> { + fn from(s: &'a T) -> Self { ImId::Str(s.as_ref()) } +} + +impl From<*const T> for ImId<'static> { + fn from(p: *const T) -> Self { ImId::Ptr(p as *const c_void) } +} + +impl From<*mut T> for ImId<'static> { + fn from(p: *mut T) -> Self { ImId::Ptr(p as *const T as *const c_void) } +} + // ID scopes impl<'ui> Ui<'ui> { /// Pushes an identifier to the ID stack. - pub fn push_id(&self, id: i32) { unsafe { sys::igPushIDInt(id) }; } + pub fn push_id<'a, I: Into>>(&self, id: I) { + let id = id.into(); + + unsafe { + match id { + ImId::Int(i) => { + sys::igPushIDInt(i); + } + ImId::Str(s) => { + let start = s.as_ptr() as *const c_char; + let end = start.offset(s.len() as isize); + sys::igPushIDStrRange(start, end); + } + ImId::Ptr(p) => { + sys::igPushIDPtr(p as *const c_void); + } + } + } + } /// Pops an identifier from the ID stack. /// @@ -565,9 +712,10 @@ impl<'ui> Ui<'ui> { pub fn pop_id(&self) { unsafe { sys::igPopID() }; } /// Runs a function after temporarily pushing a value to the ID stack. - pub fn with_id(&self, id: i32, f: F) + pub fn with_id<'a, F, I>(&self, id: I, f: F) where F: FnOnce(), + I: Into>, { self.push_id(id); f(); @@ -1201,12 +1349,25 @@ impl<'ui> Ui<'ui> { Alpha(v) => unsafe { igPushStyleVar(ImGuiStyleVar::Alpha, v) }, WindowPadding(v) => unsafe { igPushStyleVarVec(ImGuiStyleVar::WindowPadding, v) }, WindowRounding(v) => unsafe { igPushStyleVar(ImGuiStyleVar::WindowRounding, v) }, + WindowBorderSize(v) => unsafe { igPushStyleVar(ImGuiStyleVar::WindowBorderSize, v) }, WindowMinSize(v) => unsafe { igPushStyleVarVec(ImGuiStyleVar::WindowMinSize, v) }, - ChildWindowRounding(v) => unsafe { - igPushStyleVar(ImGuiStyleVar::ChildWindowRounding, v) + ChildRounding(v) => unsafe { + igPushStyleVar(ImGuiStyleVar::ChildRounding, v) + }, + ChildBorderSize(v) => unsafe { + igPushStyleVar(ImGuiStyleVar::ChildBorderSize, v) + }, + PopupRounding(v) => unsafe { + igPushStyleVar(ImGuiStyleVar::PopupRounding, v) + }, + PopupBorderSize(v) => unsafe { + igPushStyleVar(ImGuiStyleVar::PopupBorderSize, v) }, FramePadding(v) => unsafe { igPushStyleVarVec(ImGuiStyleVar::FramePadding, v) }, FrameRounding(v) => unsafe { igPushStyleVar(ImGuiStyleVar::FrameRounding, v) }, + FrameBorderSize(v) => unsafe { + igPushStyleVar(ImGuiStyleVar::FrameBorderSize, v) + }, ItemSpacing(v) => unsafe { igPushStyleVarVec(ImGuiStyleVar::ItemSpacing, v) }, ItemInnerSpacing(v) => unsafe { igPushStyleVarVec(ImGuiStyleVar::ItemInnerSpacing, v) }, IndentSpacing(v) => unsafe { igPushStyleVar(ImGuiStyleVar::IndentSpacing, v) }, @@ -1310,6 +1471,11 @@ impl<'ui> Ui<'ui> { unsafe { sys::igIsItemHovered(ImGuiHoveredFlags::empty()) } } + /// Return `true` if the current window is being hovered by the mouse. + pub fn is_window_hovered(&self) -> bool { + unsafe { sys::igIsWindowHovered(ImGuiHoveredFlags::empty()) } + } + /// Returns `true` if the last item is being active. pub fn is_item_active(&self) -> bool { unsafe { diff --git a/src/style.rs b/src/style.rs index 04c683c..5e3039b 100644 --- a/src/style.rs +++ b/src/style.rs @@ -5,13 +5,26 @@ pub enum StyleVar { Alpha(f32), WindowPadding(ImVec2), WindowRounding(f32), + WindowBorderSize(f32), WindowMinSize(ImVec2), - ChildWindowRounding(f32), + ChildRounding(f32), + ChildBorderSize(f32), + PopupRounding(f32), + PopupBorderSize(f32), FramePadding(ImVec2), FrameRounding(f32), + FrameBorderSize(f32), ItemSpacing(ImVec2), ItemInnerSpacing(ImVec2), IndentSpacing(f32), GrabMinSize(f32), ButtonTextAlign(ImVec2), } + +impl StyleVar { + #[allow(non_snake_case)] + #[deprecated(since = "0.0.19", note = "please use ChildRounding instead")] + pub fn ChildWindowRounding(value: f32) -> Self { + StyleVar::ChildRounding(value) + } +} diff --git a/src/window.rs b/src/window.rs index 40d5d6c..7f6427e 100644 --- a/src/window.rs +++ b/src/window.rs @@ -2,7 +2,7 @@ use sys; use std::marker::PhantomData; use std::ptr; -use super::{ImGuiCond, ImGuiWindowFlags, ImStr, ImVec2, Ui}; +use super::{ImGuiCond, ImGuiStyleVar, ImGuiWindowFlags, ImStr, ImVec2, Ui}; #[must_use] pub struct Window<'ui, 'p> { @@ -13,6 +13,8 @@ pub struct Window<'ui, 'p> { name: &'p ImStr, opened: Option<&'p mut bool>, flags: ImGuiWindowFlags, + // Deprecated. Should be removed along with Window::show_borders + border: bool, _phantom: PhantomData<&'ui Ui<'ui>>, } @@ -26,6 +28,7 @@ impl<'ui, 'p> Window<'ui, 'p> { name: name, opened: None, flags: ImGuiWindowFlags::empty(), + border: false, _phantom: PhantomData, } } @@ -87,8 +90,9 @@ impl<'ui, 'p> Window<'ui, 'p> { self } #[inline] + #[deprecated(since = "0.0.19", note = "please use StyleVar instead")] pub fn show_borders(mut self, value: bool) -> Self { - self.flags.set(ImGuiWindowFlags::ShowBorders, value); + self.border = value; self } #[inline] @@ -156,6 +160,9 @@ impl<'ui, 'p> Window<'ui, 'p> { if !self.size_cond.is_empty() { sys::igSetNextWindowSize(self.size.into(), self.size_cond); } + if self.border { + sys::igPushStyleVar(ImGuiStyleVar::WindowBorderSize, 1.0); + } sys::igBegin( self.name.as_ptr(), self.opened.map(|x| x as *mut bool).unwrap_or( @@ -167,6 +174,11 @@ impl<'ui, 'p> Window<'ui, 'p> { if render { f(); } - unsafe { sys::igEnd() }; + unsafe { + sys::igEnd(); + if self.border { + sys::igPopStyleVar(1); + } + }; } } diff --git a/src/window_draw_list.rs b/src/window_draw_list.rs index abc6a53..e995bd3 100644 --- a/src/window_draw_list.rs +++ b/src/window_draw_list.rs @@ -209,6 +209,23 @@ impl<'ui> WindowDrawList<'ui> { Circle::new(self, center, radius, color) } + /// Draw a text whose upper-left corner is at point `pos`. + pub fn add_text(&self, pos: P, col: C, text: T) + where + P: Into, + C: Into, + T: AsRef, + { + use std::os::raw::c_char; + + let text = text.as_ref(); + unsafe { + let start = text.as_ptr() as *const c_char; + let end = (start as usize + text.len()) as *const c_char; + sys::ImDrawList_AddText(self.draw_list, pos.into(), col.into().into(), start, end) + } + } + /// Returns a Bezier curve stretching from `pos0` to `pos1`, whose /// curvature is defined by `cp0` and `cp1`. pub fn add_bezier_curve( @@ -262,6 +279,7 @@ impl<'ui> WindowDrawList<'ui> { } /// Represents a line about to be drawn +#[must_use = "should call .build() to draw the object"] pub struct Line<'ui> { p1: ImVec2, p2: ImVec2, @@ -307,6 +325,7 @@ impl<'ui> Line<'ui> { } /// Represents a rectangle about to be drawn +#[must_use = "should call .build() to draw the object"] pub struct Rect<'ui> { p1: ImVec2, p2: ImVec2, @@ -410,6 +429,7 @@ impl<'ui> Rect<'ui> { } /// Represents a triangle about to be drawn on the window +#[must_use = "should call .build() to draw the object"] pub struct Triangle<'ui> { p1: ImVec2, p2: ImVec2, @@ -479,6 +499,7 @@ impl<'ui> Triangle<'ui> { } /// Represents a circle about to be drawn +#[must_use = "should call .build() to draw the object"] pub struct Circle<'ui> { center: ImVec2, radius: f32, @@ -553,6 +574,7 @@ impl<'ui> Circle<'ui> { } /// Represents a Bezier curve about to be drawn +#[must_use = "should call .build() to draw the object"] pub struct BezierCurve<'ui> { pos0: ImVec2, cp0: ImVec2,