diff --git a/Cargo.toml b/Cargo.toml index 6676ec0..ad3f24b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,5 @@ [workspace] -members = [ - "imgui", - "imgui-sys", - "imgui-examples", - "xtask", -] +members = ["imgui", "imgui-sys", "xtask"] package.rust-version = "1.70" -resolver = "2" +resolver = "2" \ No newline at end of file diff --git a/imgui-examples/Cargo.toml b/imgui-examples/Cargo.toml deleted file mode 100644 index 061b513..0000000 --- a/imgui-examples/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "imgui-examples" -version = "0.1.0" -edition = "2021" -description = "imgui crate examples using Glium backend" -homepage = "https://github.com/imgui-rs/imgui-rs" -repository = "https://github.com/imgui-rs/imgui-rs" -license = "MIT OR Apache-2.0" -publish = false - -[dev-dependencies] -copypasta = "0.8" -glium = { version = "0.34.0", default-features = true } -image = "0.23" -imgui = { path = "../imgui", features = ["tables-api"] } - -[dependencies] -imgui-glium-renderer = "0.12.0" -# imgui-glium-renderer = { path = "../imgui-glium-renderer" } -# imgui-winit-support = { path = "../imgui-winit-support" } diff --git a/imgui-examples/examples/collapsing_header.rs b/imgui-examples/examples/collapsing_header.rs deleted file mode 100644 index 79979dd..0000000 --- a/imgui-examples/examples/collapsing_header.rs +++ /dev/null @@ -1,70 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - let mut state = State { - render_closable: true, - }; - support::simple_init(file!(), move |run, ui| { - let w = ui - .window("Collapsing header") - .opened(run) - .position([20.0, 20.0], Condition::Appearing) - .size([700.0, 500.0], Condition::Appearing); - w.build(|| { - if CollapsingHeader::new("I'm a collapsing header. Click me!").build(ui) { - ui.text( - "A collapsing header can be used to toggle rendering of a group of widgets", - ); - } - - ui.spacing(); - if CollapsingHeader::new("I'm open by default") - .default_open(true) - .build(ui) - { - ui.text("You can still close me with a click!"); - } - - ui.spacing(); - if CollapsingHeader::new("I only open with double-click") - .open_on_double_click(true) - .build(ui) - { - ui.text("Double the clicks, double the fun!"); - } - - ui.spacing(); - if CollapsingHeader::new("I don't have an arrow") - .bullet(true) - .build(ui) - { - ui.text("Collapsing headers can use a bullet instead of an arrow"); - } - - ui.spacing(); - if CollapsingHeader::new("I only open if you click the arrow") - .open_on_arrow(true) - .build(ui) - { - ui.text("You clicked the arrow"); - } - - ui.spacing(); - ui.checkbox( - "Toggle rendering of the next example", - &mut state.render_closable, - ); - if CollapsingHeader::new("I've got a separate close button") - .build_with_close_button(ui, &mut state.render_closable) - { - ui.text("I've got contents just like any other collapsing header"); - } - }); - }); -} - -struct State { - render_closable: bool, -} diff --git a/imgui-examples/examples/color_button.rs b/imgui-examples/examples/color_button.rs deleted file mode 100644 index c5aacc5..0000000 --- a/imgui-examples/examples/color_button.rs +++ /dev/null @@ -1,156 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - let mut state = State::default(); - support::simple_init(file!(), move |run, ui| { - example_selector(run, ui, &mut state); - match state.example { - 1 => example_1(ui, &mut state), - 2 => example_2(ui), - 3 => example_3(ui), - _ => (), - } - }); -} - -fn example_selector(run: &mut bool, ui: &mut Ui, state: &mut State) { - let w = ui - .window("Color button examples") - .opened(run) - .position([20.0, 20.0], Condition::Appearing) - .size([700.0, 100.0], Condition::Appearing) - .resizable(false); - w.build(|| { - let ex1 = ui.radio_button("Example 1: Basics", &mut state.example, 1); - let ex2 = ui.radio_button("Example 2: Alpha component", &mut state.example, 2); - let ex3 = ui.radio_button("Example 3: Input format", &mut state.example, 3); - if ex1 || ex2 || ex3 { - state.reset(); - } - }); -} - -fn example_1(ui: &Ui, state: &mut State) { - let w = ui - .window("Example 1: Basics") - .size([700.0, 300.0], Condition::Appearing) - .position([20.0, 140.0], Condition::Appearing); - w.build(|| { - ui.text_wrapped( - "Color button is a widget that displays a color value as a clickable rectangle. \ - It also supports a tooltip with detailed information about the color value. \ - Try hovering over and clicking these buttons!", - ); - ui.text(state.notify_text); - - ui.text("This button is black:"); - if ui.color_button("Black color", [0.0, 0.0, 0.0, 1.0]) { - state.notify_text = "*** Black button was clicked"; - } - - ui.text("This button is red:"); - if ui.color_button("Red color", [1.0, 0.0, 0.0, 1.0]) { - state.notify_text = "*** Red button was clicked"; - } - - ui.text("This button is BIG because it has a custom size:"); - if ui - .color_button_config("Green color", [0.0, 1.0, 0.0, 1.0]) - .size([100.0, 50.0]) - .build() - { - state.notify_text = "*** BIG button was clicked"; - } - - ui.text("This button doesn't use the tooltip at all:"); - if ui - .color_button_config("No tooltip", [0.0, 0.0, 1.0, 1.0]) - .tooltip(false) - .build() - { - state.notify_text = "*** No tooltip button was clicked"; - } - }); -} - -fn example_2(ui: &Ui) { - let w = ui - .window("Example 2: Alpha component") - .size([700.0, 320.0], Condition::Appearing) - .position([20.0, 140.0], Condition::Appearing); - w.build(|| { - ui.text_wrapped( - "The displayed color is passed to the button as four float values between \ - 0.0 - 1.0 (RGBA). If you don't care about the alpha component, it can be \ - disabled and it won't show up in the tooltip", - ); - - ui.text("This button ignores the alpha component:"); - ui.color_button_config("Red color", [1.0, 0.0, 0.0, 0.5]) - .alpha(false) - .build(); - - ui.spacing(); - ui.spacing(); - ui.spacing(); - ui.text_wrapped( - "If you *do* care about the alpha component, you can choose how it's \ - displayed in the button and the tooltip", - ); - - ui.separator(); - ui.text_wrapped("ColorPreview::Opaque (default) doesn't show the alpha component at all"); - ui.color_button_config("Red + ColorPreview::Opaque", [1.0, 0.0, 0.0, 0.5]) - .preview(ColorPreview::Opaque) - .build(); - - ui.separator(); - ui.text_wrapped( - "ColorPreview::HalfAlpha divides the color area into two halves and uses a \ - checkerboard pattern in one half to illustrate the alpha component", - ); - ui.color_button_config("Red + ColorPreview::HalfAlpha", [1.0, 0.0, 0.0, 0.5]) - .preview(ColorPreview::HalfAlpha) - .build(); - - ui.separator(); - ui.text_wrapped( - "ColorPreview::Alpha uses a checkerboard pattern in the entire color area to \ - illustrate the alpha component", - ); - ui.color_button_config("Red + ColorPreview::Alpha", [1.0, 0.0, 0.0, 0.5]) - .preview(ColorPreview::Alpha) - .build(); - }); -} - -fn example_3(ui: &Ui) { - let w = ui - .window("Example 3: Input format") - .size([700.0, 320.0], Condition::Appearing) - .position([20.0, 140.0], Condition::Appearing); - w.build(|| { - ui.text("This button interprets the input value [1.0, 0.0, 0.0, 1.0] as RGB(A) (default):"); - ui.color_button("RGBA red", [1.0, 0.0, 0.0, 1.0]); - - ui.separator(); - ui.text("This button interprets the input value [1.0, 0.0, 0.0, 1.0] as HSV(A):"); - ui.color_button_config("HSVA black", [1.0, 0.0, 0.0, 1.0]) - .input_mode(ColorEditInputMode::HSV) - .build(); - }); -} - -#[derive(Default)] -struct State { - example: u32, - notify_text: &'static str, -} - -impl State { - fn reset(&mut self) { - self.notify_text = ""; - } -} diff --git a/imgui-examples/examples/creating_windows.rs b/imgui-examples/examples/creating_windows.rs deleted file mode 100644 index 6807007..0000000 --- a/imgui-examples/examples/creating_windows.rs +++ /dev/null @@ -1,65 +0,0 @@ -mod support; - -fn main() { - support::simple_init(file!(), move |_, ui| { - // If we don't explicitly create a window before creating some kind of widget, then Dear Imgui will automatically create one - ui.text("This text will appear in a default window titled 'Debug'"); - - // However, in almost all cases it's best to make a window, so it has a useful title etc - - // imgui-rs has two main methods of creating windows (and these same approaches - // apply to many other widgets). First, callback based: - - ui.window("My window via callback").build(|| { - ui.text("This content appears in a window"); - - // Everything in this callback appears in the window, like this button: - ui.button("This button"); - }); - - // Often the callback approach is most convenient, however occasionally the callbacks can be hard to use. - // In this case, there is the "token based" approach. You call a method and get a "window token", - // everything that happens until the token is dropped is included in the window this is more-or-less how - // the Dear ImGui C++ API works) - - // Here we (maybe) get a window token: - let window_token = ui.window("Token based window").begin(); - if let Some(_t) = window_token { - // If the token is Some(...) then the window contents are visible, so we need to draw them! - ui.text("Window contents!") - } - - // Here we create a window with a specific size, and force it to always have a vertical scrollbar visible - ui.window("Big complex window") - .size([200.0, 100.0], imgui::Condition::FirstUseEver) - .always_vertical_scrollbar(true) - .build(|| { - ui.text("Imagine something complicated here.."); - - // Note you can create windows inside other windows, however, they both appear as separate windows. - // For example, somewhere deep inside a complex window, we can quickly create a widget to display a - // variable, like a graphical "debug print" - ui.window("Confusion") - .build(|| ui.text(format!("Some variable: {:?}", ui.io().mouse_pos))) - }); - - // If you want to nest windows inside other windows, you can a "child window". - // This is essentially a scrollable area, with all the same properties as a regular window - ui.window("Parent window").build(|| { - ui.child_window("Child window") - .size([100.0, 100.0]) - .build(|| { - for _ in 0..10 { - ui.text("Lines and"); - } - }); - ui.child_window("Second child window") - .size([100.0, 100.0]) - .build(|| { - for _ in 0..10 { - ui.text("More and"); - } - }); - }); - }); -} diff --git a/imgui-examples/examples/custom_textures.rs b/imgui-examples/examples/custom_textures.rs deleted file mode 100644 index 3c6be5d..0000000 --- a/imgui-examples/examples/custom_textures.rs +++ /dev/null @@ -1,233 +0,0 @@ -use std::borrow::Cow; -use std::error::Error; -use std::io::Cursor; -use std::rc::Rc; - -use glium::{ - backend::Facade, - texture::{ClientFormat, RawImage2d}, - uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerBehavior}, - Texture2d, -}; -use image::{jpeg::JpegDecoder, ImageDecoder}; -use imgui::*; -use imgui_glium_renderer::Texture; - -mod support; - -#[derive(Default)] -struct CustomTexturesApp { - my_texture_id: Option, - lenna: Option, -} - -struct Lenna { - texture_id: TextureId, - size: [f32; 2], -} - -impl CustomTexturesApp { - fn register_textures( - &mut self, - gl_ctx: &F, - textures: &mut Textures, - ) -> Result<(), Box> - where - F: Facade, - { - const WIDTH: usize = 100; - const HEIGHT: usize = 100; - - if self.my_texture_id.is_none() { - // Generate dummy texture - let mut data = Vec::with_capacity(WIDTH * HEIGHT); - for i in 0..WIDTH { - for j in 0..HEIGHT { - // Insert RGB values - data.push(i as u8); - data.push(j as u8); - data.push((i + j) as u8); - } - } - - let raw = RawImage2d { - data: Cow::Owned(data), - width: WIDTH as u32, - height: HEIGHT as u32, - format: ClientFormat::U8U8U8, - }; - let gl_texture = Texture2d::new(gl_ctx, raw)?; - let texture = Texture { - texture: Rc::new(gl_texture), - sampler: SamplerBehavior { - magnify_filter: MagnifySamplerFilter::Linear, - minify_filter: MinifySamplerFilter::Linear, - ..Default::default() - }, - }; - let texture_id = textures.insert(texture); - - self.my_texture_id = Some(texture_id); - } - - if self.lenna.is_none() { - self.lenna = Some(Lenna::new(gl_ctx, textures)?); - } - - Ok(()) - } - - fn show_textures(&self, ui: &Ui) { - ui.window("Hello textures") - .size([400.0, 400.0], Condition::FirstUseEver) - .build(|| { - ui.text("Hello textures!"); - if let Some(my_texture_id) = self.my_texture_id { - ui.text("Some generated texture"); - Image::new(my_texture_id, [100.0, 100.0]).build(ui); - } - - if let Some(lenna) = &self.lenna { - ui.text("Say hello to Lenna.jpg"); - lenna.show(ui); - } - - // Example of using custom textures on a button - if let Some(lenna) = &self.lenna { - ui.text("The Lenna buttons"); - - { - ui.invisible_button("Boring Button", [100.0, 100.0]); - // See also `imgui::Ui::style_color` - let tint_none = [1.0, 1.0, 1.0, 1.0]; - let tint_green = [0.5, 1.0, 0.5, 1.0]; - let tint_red = [1.0, 0.5, 0.5, 1.0]; - - let tint = match ( - ui.is_item_hovered(), - ui.is_mouse_down(imgui::MouseButton::Left), - ) { - (false, false) => tint_none, - (false, true) => tint_none, - (true, false) => tint_green, - (true, true) => tint_red, - }; - - let draw_list = ui.get_window_draw_list(); - draw_list - .add_image(lenna.texture_id, ui.item_rect_min(), ui.item_rect_max()) - .col(tint) - .build(); - } - - { - ui.same_line(); - - // Button using quad positioned image - ui.invisible_button("Exciting Button", [100.0, 100.0]); - - // Button bounds - let min = ui.item_rect_min(); - let max = ui.item_rect_max(); - - // get corner coordinates - let tl = [ - min[0], - min[1] + (ui.frame_count() as f32 / 10.0).cos() * 10.0, - ]; - let tr = [ - max[0], - min[1] + (ui.frame_count() as f32 / 10.0).sin() * 10.0, - ]; - let bl = [min[0], max[1]]; - let br = max; - - let draw_list = ui.get_window_draw_list(); - draw_list - .add_image_quad(lenna.texture_id, tl, tr, br, bl) - .build(); - } - - // Rounded image - { - ui.same_line(); - ui.invisible_button("Smooth Button", [100.0, 100.0]); - - let draw_list = ui.get_window_draw_list(); - draw_list - .add_image_rounded( - lenna.texture_id, - ui.item_rect_min(), - ui.item_rect_max(), - 16.0, - ) - // Tint brighter for visiblity of corners - .col([2.0, 0.5, 0.5, 1.0]) - // Rounding on each corner can be changed separately - .round_top_left(ui.frame_count() / 60 % 4 == 0) - .round_top_right((ui.frame_count() + 1) / 60 % 4 == 1) - .round_bot_right((ui.frame_count() + 3) / 60 % 4 == 2) - .round_bot_left((ui.frame_count() + 2) / 60 % 4 == 3) - .build(); - } - } - }); - } -} - -impl Lenna { - fn new(gl_ctx: &F, textures: &mut Textures) -> Result> - where - F: Facade, - { - let lenna_bytes = include_bytes!("../../resources/Lenna.jpg"); - let byte_stream = Cursor::new(lenna_bytes.as_ref()); - let decoder = JpegDecoder::new(byte_stream)?; - - let (width, height) = decoder.dimensions(); - let mut image = vec![0; decoder.total_bytes() as usize]; - decoder.read_image(&mut image)?; - let raw = RawImage2d { - data: Cow::Owned(image), - width, - height, - format: ClientFormat::U8U8U8, - }; - let gl_texture = Texture2d::new(gl_ctx, raw)?; - let texture = Texture { - texture: Rc::new(gl_texture), - sampler: SamplerBehavior { - magnify_filter: MagnifySamplerFilter::Linear, - minify_filter: MinifySamplerFilter::Linear, - ..Default::default() - }, - }; - let texture_id = textures.insert(texture); - Ok(Lenna { - texture_id, - size: [width as f32, height as f32], - }) - } - - fn show(&self, ui: &Ui) { - Image::new(self.texture_id, self.size).build(ui); - } -} - -fn main() { - let my_app = std::rc::Rc::new(std::cell::RefCell::new(CustomTexturesApp::default())); - let app_clone = my_app.clone(); - - support::init_with_startup( - file!(), - move |_ctx, renderer, display| { - app_clone - .borrow_mut() - .register_textures(display.get_context(), renderer.textures()) - .expect("Failed to register textures"); - }, - move |_, ui| { - my_app.borrow_mut().show_textures(ui); - }, - ); -} diff --git a/imgui-examples/examples/disablement.rs b/imgui-examples/examples/disablement.rs deleted file mode 100644 index 98f081d..0000000 --- a/imgui-examples/examples/disablement.rs +++ /dev/null @@ -1,58 +0,0 @@ -//! Demonstrates disabling widgets. Prevents mouse interaction and greys out widgets - -use imgui::*; - -mod support; - -fn main() { - let mut edit_mode = true; - let mut safe_mode = true; - - let mut click_count = 0; - support::simple_init(file!(), move |_, ui| { - ui.window("Disabling widgets") - .size([300.0, 200.0], Condition::FirstUseEver) - .build(|| { - ui.checkbox("Edit mode", &mut edit_mode); - ui.checkbox("Safe mode", &mut safe_mode); - - ui.separator(); - - // Disable entire rest of widget unless in edit mode - let _d = ui.begin_enabled(edit_mode); - - if ui.button("Button 1") { - click_count += 1; - } - if ui.button("Button 2") { - click_count += 1; - } - - // Disable dangerous buttons when in safe mode - ui.disabled(safe_mode, || { - let _red = ui.push_style_color(StyleColor::Button, [1.0, 0.0, 0.0, 1.0]); - if ui.button("Dangerous button!") { - click_count -= 1; - } - }); - - // Can also create a token in a specific scope - { - let _danger_token = ui.begin_disabled(safe_mode); - if ui.button("Button 3") { - click_count += 1; - } - // _danger_token implicitly dropped here - } - - // Or manually drop the token - let danger_token2 = ui.begin_disabled(safe_mode); - if ui.button("Button 4") { - click_count += 1; - } - danger_token2.end(); - - // Note the `_d` token is dropped here automatically - }); - }); -} diff --git a/imgui-examples/examples/draw_list.rs b/imgui-examples/examples/draw_list.rs deleted file mode 100644 index 053bb60..0000000 --- a/imgui-examples/examples/draw_list.rs +++ /dev/null @@ -1,136 +0,0 @@ -use imgui::*; - -mod support; - -// rect is [x, y, w, h] -fn draw_text_centered( - ui: &Ui, - draw_list: &DrawListMut, - rect: [f32; 4], - text: &str, - color: [f32; 3], -) { - let text_size = ui.calc_text_size(text); - let cx = (rect[2] - text_size[0]) / 2.0; - let cy = (rect[3] - text_size[1]) / 2.0; - draw_list.add_text([rect[0] + cx, rect[1] + cy], color, text); -} - -fn main() { - support::simple_init(file!(), move |_, ui| { - // Get access to draw FG and BG draw lists. - let bg_draw_list = ui.get_background_draw_list(); - let fg_draw_list = ui.get_foreground_draw_list(); - - // Note we cannot access two instances of the same draw list - // at once. That is to say, the following line would panic if - // uncommented: - //let bg_draw_list_2 = ui.get_background_draw_list(); // panic! - - { - bg_draw_list - .add_circle([150.0, 150.0], 150.0, [1.0, 0.0, 0.0]) - .thickness(4.0) - .build(); - draw_text_centered( - ui, - &bg_draw_list, - [0.0, 0.0, 300.0, 300.0], - "background draw list", - [0.0, 0.0, 0.0], - ); - } - - { - let [w, h] = ui.io().display_size; - fg_draw_list - .add_circle([w - 150.0, h - 150.0], 150.0, [1.0, 0.0, 0.0]) - .thickness(4.0) - .build(); - draw_text_centered( - ui, - &fg_draw_list, - [w - 300.0, h - 300.0, 300.0, 300.0], - "foreground draw list", - [1.0, 0.0, 0.0], - ); - } - - ui.window("Draw list") - .size([300.0, 110.0], Condition::FirstUseEver) - .scroll_bar(false) - .build(|| { - ui.button("random button"); - let draw_list = ui.get_window_draw_list(); - let o = ui.cursor_screen_pos(); - let ws = ui.content_region_avail(); - draw_list - .add_circle([o[0] + 10.0, o[1] + 10.0], 5.0, [1.0, 0.0, 0.0]) - .thickness(4.0) - .build(); - draw_list - .add_circle([o[0] + ws[0] - 10.0, o[1] + 10.0], 5.0, [0.0, 1.0, 0.0]) - .thickness(4.0) - .build(); - draw_list - .add_circle( - [o[0] + ws[0] - 10.0, o[1] + ws[1] - 10.0], - 5.0, - [0.0, 0.0, 1.0], - ) - .thickness(4.0) - .build(); - draw_list - .add_circle([o[0] + 10.0, o[1] + ws[1] - 10.0], 5.0, [1.0, 1.0, 0.0]) - .thickness(4.0) - .build(); - draw_text_centered( - ui, - &draw_list, - [o[0], o[1], ws[0], ws[1]], - "window draw list", - [1.0, 1.0, 1.0], - ); - }); - - ui.window("Polygons") - .size([300.0, 150.0], Condition::FirstUseEver) - .position([400.0, 110.0], Condition::FirstUseEver) - .scroll_bar(false) - .build(|| { - let draw_list = ui.get_window_draw_list(); - - // Origin - let o = ui.cursor_screen_pos(); - - draw_list - .add_polyline( - vec![ - [o[0] + 0.0, o[1] + 0.0], - [o[0] + 100.0, o[1] + 25.0], - [o[0] + 50.0, o[1] + 50.0], - [o[0] + 100.0, o[1] + 75.0], - [o[0] + 0.0, o[1] + 100.0], - [o[0] + 0.0, o[1] + 0.0], - ], - [1.0, 0.0, 1.0], - ) - .build(); - - draw_list - .add_polyline( - vec![ - [o[0] + 120.0 + 0.0, o[1] + 0.0], - [o[0] + 120.0 + 100.0, o[1] + 25.0], - [o[0] + 120.0 + 50.0, o[1] + 50.0], - [o[0] + 120.0 + 100.0, o[1] + 75.0], - [o[0] + 120.0 + 0.0, o[1] + 100.0], - [o[0] + 120.0 + 0.0, o[1] + 0.0], - ], - [0.0, 1.0, 1.0], - ) - .filled(true) - .build(); - }); - }); -} diff --git a/imgui-examples/examples/empty.rs b/imgui-examples/examples/empty.rs deleted file mode 100644 index b61c06c..0000000 --- a/imgui-examples/examples/empty.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod support; - -fn main() { - support::simple_init(file!(), move |_, _ui| { - // nothing! don't actually do any imgui funtimes - }); -} diff --git a/imgui-examples/examples/hello_world.rs b/imgui-examples/examples/hello_world.rs deleted file mode 100644 index 59ab0c1..0000000 --- a/imgui-examples/examples/hello_world.rs +++ /dev/null @@ -1,28 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - let mut value = 0; - let choices = ["test test this is 1", "test test this is 2"]; - support::simple_init(file!(), move |_, ui| { - ui.window("Hello world") - .size([300.0, 110.0], Condition::FirstUseEver) - .build(|| { - ui.text_wrapped("Hello world!"); - ui.text_wrapped("こんにちは世界!"); - if ui.button(choices[value]) { - value += 1; - value %= 2; - } - - ui.button("This...is...imgui-rs!"); - ui.separator(); - let mouse_pos = ui.io().mouse_pos; - ui.text(format!( - "Mouse Position: ({:.1},{:.1})", - mouse_pos[0], mouse_pos[1] - )); - }); - }); -} diff --git a/imgui-examples/examples/id_wrangling.rs b/imgui-examples/examples/id_wrangling.rs deleted file mode 100644 index e6d1dc1..0000000 --- a/imgui-examples/examples/id_wrangling.rs +++ /dev/null @@ -1,44 +0,0 @@ -mod support; - -fn main() { - support::simple_init(file!(), move |_, ui| { - let items = vec!["a", "b", "c", "d"]; - - ui.window("Broken Example") - .position([0.0, 0.0], imgui::Condition::FirstUseEver) - .size([390.0, 200.0], imgui::Condition::FirstUseEver) - .build(|| { - ui.text("Broken! Only first button responds to clicks"); - - // Because all our buttons have the same label (and thus ID), - // only the first button responds to clicks! - for it in &items { - ui.text(it); - for num in 0..5 { - ui.same_line(); - if ui.button("Example") { - println!("{}: {}", it, num); - } - } - } - }); - - ui.window("Good Example") - .position([400.0, 0.0], imgui::Condition::FirstUseEver) - .size([390.0, 200.0], imgui::Condition::FirstUseEver) - .build(|| { - ui.text("Works!"); - for it in &items { - let _label_id = ui.push_id(it); - ui.text(it); - for num in 0..5 { - let _num_id = ui.push_id_usize(num); - ui.same_line(); - if ui.button("Example") { - println!("{}: {}", it, num); - } - } - } - }); - }); -} diff --git a/imgui-examples/examples/keyboard.rs b/imgui-examples/examples/keyboard.rs deleted file mode 100644 index a645e41..0000000 --- a/imgui-examples/examples/keyboard.rs +++ /dev/null @@ -1,143 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - let mut press_counter = 0u32; - let mut press_no_repeat_counter = 0u32; - let mut release_counter = 0u32; - let mut ctrl_a_counter = 0u32; - let mut uncaptured_counter = 0u32; - let mut home_counter = 0u32; - let mut f1_release_count = 0u32; - let mut text_buffer = String::new(); - - support::simple_init(file!(), move |_, ui| { - ui.window("Means of accessing key state") - .size([500.0, 300.0], Condition::FirstUseEver) - .build(|| { - // You can check if a key is currently held down - if ui.is_key_down(Key::A) { - ui.text("The A key is down!"); - } else { - ui.text("The A key is not down"); - } - - // You can also check if the key has been pressed - // down, which is true for one frame. This has "key - // repeat" so will be true again based on the repeat - // delay and rate. - if ui.is_key_pressed(Key::A) { - press_counter += 1; - } - ui.text(format!( - "The A key has been pressed {} times", - press_counter - )); - - // You can also check if the key has been pressed - // down, which is true for one frame. This has "key - // repeat" so will be true again based on the repeat - // delay and rate. - if ui.is_key_pressed_no_repeat(Key::A) { - press_no_repeat_counter += 1; - } - ui.text(format!( - "The A key has been pressed {} times (ignoring key repeat)", - press_no_repeat_counter - )); - - // Note due to the key-repeat behaviour that the key - // may be pressed more often than it is released. - if ui.is_key_released(Key::A) { - release_counter += 1; - } - ui.text(format!( - "The A key has been released {} times", - release_counter - )); - - // Modifiers are accessed via bools on the `imgui::Io` - // struct, - if ui.io().key_ctrl { - ui.text("Ctrl is down!"); - } else { - ui.text("Ctrl is up!"); - } - - // Using modifiers in conjunction with key press - // events is simple: - if ui.io().key_ctrl && ui.is_key_released(Key::A) { - ctrl_a_counter += 1; - } - ui.text(format!( - "The Ctrl+A key has been released {} times", - ctrl_a_counter - )); - - // Note that `is_key_released` gives the state of the - // key regardless of what widget has focus, for - // example, if you try to type into this input, the - // above interaction still counts the key presses. - ui.input_text_multiline( - "##Dummy text input widget", - &mut text_buffer, - [100.0, 100.0], - ) - // .do_not_resize() if you pass this, then this won't resize! - // .hint("Example text input") - .build(); - - // If you want to check if a widget is capturing - // keyboard input, you can check - // `Io::want_capture_keyboard` - if !ui.io().want_capture_keyboard && ui.is_key_pressed(Key::A) { - uncaptured_counter += 1; - } - ui.text(format!( - "There has been {} uncaptured A key presses", - uncaptured_counter - )); - - // These examples all use `Key::A`. The `imgui::Key` - // enum only contains the few keys which imgui - // internally uses (such as for the `Ctrl + A` select - // all shortcut). This may expand in future versions - // of imgui, but will likely never contain every - // possible key - // - // Instead we can use keys using an index, the meaning - // of which is defined by the implementation of "IO" - // backend. - // - // For example, in the `WinitPlatform` backend each - // key is indexed by it's integer value of - // `winit::VirtualKeyCode`. So we can query if a key - // is down based on it's virtual key code, - - if ui.is_key_down(Key::Home) { - home_counter += 1; - } - ui.text(format!("Home has been pressed for {} frames", home_counter)); - // It is important to remember that unlike using - // `imgui::Key`, there is nothing enforcing the index - // is the key you expect. For example if you hardcode - // your key ID's and switch backends, you may be - // querying different keys! - if ui.io().keys_down[123] { - // A mystery key is down! - } - - // It is also possible to use the `is_key_...` methods - // with arbitrary key indexes. For example, to check - // if the F1 key is been pressed - - if ui.is_key_released(Key::F1) { - // Index is hardcoded for imgui-examples only, instead do this: - //if ui.is_key_index_released(winit::event::VirtualKeyCode::F1 as i32) { - f1_release_count += 1; - } - ui.text(format!("F1 has been released {} times", f1_release_count)); - }); - }); -} diff --git a/imgui-examples/examples/long_list.rs b/imgui-examples/examples/long_list.rs deleted file mode 100644 index 7031172..0000000 --- a/imgui-examples/examples/long_list.rs +++ /dev/null @@ -1,45 +0,0 @@ -/// Demonstrates using the "list clipper" to efficiently display long -/// lists in a scrolling area. -/// -/// You specify the height per item, and the `ListClipper` API will -/// provide which item index are visible. This avoids having to create -/// thousands of items only for them to not be made visible. -/// -/// Note this requires a fixed (or easily computable) height per item. -use imgui::*; - -mod support; - -fn main() { - let lots_of_words: Vec = (0..10000).map(|x| format!("Line {}", x)).collect(); - - support::simple_init(file!(), move |_, ui| { - // Show the C++ style API - ui.window("Hello long world") - .size([100.0, 500.0], Condition::FirstUseEver) - .position([10.0, 10.0], crate::Condition::Always) - .build(|| { - let mut clipper = imgui::ListClipper::new(lots_of_words.len() as i32) - .items_height(ui.current_font_size()) - .begin(ui); - while clipper.step() { - for row_num in clipper.display_start()..clipper.display_end() { - ui.text(&lots_of_words[row_num as usize]); - } - } - }); - - // Show the more Rust'y iterator - ui.window("Hello long world (iterator API)") - .size([100.0, 500.0], Condition::FirstUseEver) - .position([150.0, 10.0], crate::Condition::Always) - .build(|| { - let clipper = imgui::ListClipper::new(lots_of_words.len() as i32) - .items_height(ui.current_font_size()) - .begin(ui); - for row_num in clipper.iter() { - ui.text(&lots_of_words[row_num as usize]); - } - }); - }); -} diff --git a/imgui-examples/examples/long_table.rs b/imgui-examples/examples/long_table.rs deleted file mode 100644 index 6a60a8a..0000000 --- a/imgui-examples/examples/long_table.rs +++ /dev/null @@ -1,50 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - support::simple_init(file!(), move |_, ui| { - ui.show_demo_window(&mut true); - - ui.window("Table with list clipper") - .size([800.0, 700.0], Condition::FirstUseEver) - .build(|| { - let num_cols = 3; - let num_rows = 1000; - - let flags = imgui::TableFlags::ROW_BG - | imgui::TableFlags::RESIZABLE - | imgui::TableFlags::BORDERS_H - | imgui::TableFlags::BORDERS_V; //| imgui::TableFlags::SCROLL_Y; - - if let Some(_t) = ui.begin_table_with_sizing( - "longtable", - num_cols, - flags, - [300.0, 100.0], - /*inner width=*/ 0.0, - ) { - ui.table_setup_column("A"); - ui.table_setup_column("B"); - ui.table_setup_column("C"); - - // Freeze first row so headers are visible even - // when scrolling - ui.table_setup_scroll_freeze(num_cols, 1); - - // Done with headers row - ui.table_headers_row(); - - // Create clipper with st - let clip = imgui::ListClipper::new(num_rows).begin(ui); - for row_num in clip.iter() { - ui.table_next_row(); - for col_num in 0..num_cols { - ui.table_set_column_index(col_num); - ui.text(format!("Hello {},{}", col_num, row_num)); - } - } - } - }); - }); -} diff --git a/imgui-examples/examples/multiple_fonts.rs b/imgui-examples/examples/multiple_fonts.rs deleted file mode 100644 index 77e8246..0000000 --- a/imgui-examples/examples/multiple_fonts.rs +++ /dev/null @@ -1,58 +0,0 @@ -use imgui::*; - -mod support; - -/// NOTE on this example: -/// Most of this complexity is because of how we initialize our support -/// (which primarily is a result of `winit`'s requirements for making a window). -/// In reality, most of these two functions can be made directly after each other -- -/// to run the initialization code (which loads a font), all you need is imgui + a renderer. -fn main() { - let dokdo = std::rc::Rc::new(std::cell::RefCell::new(None)); - let roboto = std::rc::Rc::new(std::cell::RefCell::new(None)); - - let dokdo_init = dokdo.clone(); - let roboto_init = roboto.clone(); - - support::init_with_startup( - file!(), - move |ctx, renderer, _| { - let mut dokdo_handle = dokdo_init.borrow_mut(); - let mut roboto_handle = roboto_init.borrow_mut(); - - // this function runs right after the window is created. - // In your own code, this can be done whenever you have a renderer - // and a context. - *dokdo_handle = Some(ctx.fonts().add_font(&[FontSource::TtfData { - data: include_bytes!("../../resources/Dokdo-Regular.ttf"), - size_pixels: support::FONT_SIZE, - config: None, - }])); - *roboto_handle = Some(ctx.fonts().add_font(&[FontSource::TtfData { - data: include_bytes!("../../resources/Roboto-Regular.ttf"), - size_pixels: support::FONT_SIZE, - config: None, - }])); - - renderer - .reload_font_texture(ctx) - .expect("Failed to reload fonts"); - }, - move |run, ui| { - let dokdo = dokdo.borrow().unwrap(); - let roboto = roboto.borrow().unwrap(); - - ui.window("Hello world").opened(run).build(|| { - ui.text("Hello, I'm the default font!"); - let _roboto = ui.push_font(roboto); - ui.text("Hello, I'm Roboto Regular!"); - let _dokdo = ui.push_font(dokdo); - ui.text("Hello, I'm Dokdo Regular!"); - _dokdo.pop(); - ui.text("Hello, I'm Roboto Regular again!"); - _roboto.pop(); - ui.text("Hello, I'm the default font again!"); - }); - }, - ); -} diff --git a/imgui-examples/examples/progress_bar.rs b/imgui-examples/examples/progress_bar.rs deleted file mode 100644 index 4e16b6e..0000000 --- a/imgui-examples/examples/progress_bar.rs +++ /dev/null @@ -1,25 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - support::simple_init(file!(), move |run, ui| { - let w = ui - .window("Progress bar") - .opened(run) - .position([20.0, 20.0], Condition::Appearing) - .size([700.0, 200.0], Condition::Appearing); - w.build(|| { - ui.text("This is a simple progress bar:"); - ProgressBar::new(0.5).build(ui); - - ui.separator(); - ui.text("This progress bar has a custom size:"); - ProgressBar::new(0.3).size([200.0, 50.0]).build(ui); - - ui.separator(); - ui.text("This progress bar uses overlay text:"); - ProgressBar::new(0.8).overlay_text("Lorem ipsum").build(ui); - }); - }); -} diff --git a/imgui-examples/examples/radio_button.rs b/imgui-examples/examples/radio_button.rs deleted file mode 100644 index bbef1e8..0000000 --- a/imgui-examples/examples/radio_button.rs +++ /dev/null @@ -1,120 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - let mut state = State::default(); - support::simple_init(file!(), move |run, ui| { - example_selector(run, ui, &mut state); - match state.example { - 1 => example_1(ui, &mut state), - 2 => example_2(ui, &mut state), - _ => (), - } - }); -} - -fn example_selector(run: &mut bool, ui: &mut Ui, state: &mut State) { - let w = ui - .window("Radio button examples") - .opened(run) - .position([20.0, 20.0], Condition::Appearing) - .size([700.0, 80.0], Condition::Appearing) - .resizable(false); - w.build(|| { - let mut clicked = false; - clicked |= ui.radio_button("Example 1: Boolean radio buttons", &mut state.example, 1); - clicked |= ui.radio_button("Example 2: Radio buttons", &mut state.example, 2); - if clicked { - state.reset(); - } - }); -} - -fn example_1(ui: &Ui, state: &mut State) { - let w = ui - .window("Example 1: Boolean radio buttons") - .size([700.0, 200.0], Condition::Appearing) - .position([20.0, 120.0], Condition::Appearing); - w.build(|| { - ui.text_wrapped( - "Boolean radio buttons accept a boolean active state, which is passed as a value and \ - not as a mutable reference. This means that it's not updated automatically, so you \ - can implement any click behaviour you want. The return value is true if the button \ - was clicked.", - ); - ui.text(state.notify_text); - - if ui.radio_button_bool("I'm permanently active", true) { - state.notify_text = "*** Permanently active radio button was clicked"; - } - if ui.radio_button_bool("I'm permanently inactive", false) { - state.notify_text = "*** Permanently inactive radio button was clicked"; - } - if ui.radio_button_bool("I toggle my state on click", state.simple_bool) { - state.simple_bool = !state.simple_bool; // flip state on click - state.notify_text = "*** Toggling radio button was clicked"; - } - }); -} - -fn example_2(ui: &Ui, state: &mut State) { - let w = ui - .window("Example 2: Radio buttons") - .size([700.0, 300.0], Condition::Appearing) - .position([20.0, 120.0], Condition::Appearing); - w.build(|| { - ui.text_wrapped( - "Normal radio buttons accept a mutable reference to state, and the value \ - corresponding to this button. They are very flexible, because the value can be any \ - type that is both Copy and PartialEq. This is especially useful with Rust enums", - ); - ui.text(state.notify_text); - - ui.separator(); - if ui.radio_button("I'm number 1", &mut state.number, 1) { - state.notify_text = "*** Number 1 was clicked"; - } - if ui.radio_button("I'm number 2", &mut state.number, 2) { - state.notify_text = "*** Number 2 was clicked"; - } - if ui.radio_button("I'm number 3", &mut state.number, 3) { - state.notify_text = "*** Number 3 was clicked"; - } - - ui.separator(); - if ui.radio_button("I'm choice A", &mut state.choice, Some(Choice::A)) { - state.notify_text = "*** Choice A was clicked"; - } - if ui.radio_button("I'm choice B", &mut state.choice, Some(Choice::B)) { - state.notify_text = "*** Choice B was clicked"; - } - if ui.radio_button("I'm choice C", &mut state.choice, Some(Choice::C)) { - state.notify_text = "*** Choice C was clicked"; - } - }); -} - -#[derive(Default)] -struct State { - example: u32, - notify_text: &'static str, - simple_bool: bool, - number: u8, - // We use Option here because we don't want any initial value. - // Another choice could be to choose one of the Choice enum values to be the default. - choice: Option, -} - -#[derive(Copy, Clone, PartialEq)] -enum Choice { - A, - B, - C, -} - -impl State { - fn reset(&mut self) { - self.notify_text = ""; - } -} diff --git a/imgui-examples/examples/slider.rs b/imgui-examples/examples/slider.rs deleted file mode 100644 index 8bdd853..0000000 --- a/imgui-examples/examples/slider.rs +++ /dev/null @@ -1,104 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - let mut state = State::default(); - support::simple_init(file!(), move |run, ui| { - example_selector(run, ui, &mut state); - match state.example { - 1 => example_1(ui, &mut state), - 2 => example_2(ui, &mut state), - _ => (), - } - }); -} - -fn example_selector(run: &mut bool, ui: &mut Ui, state: &mut State) { - let w = ui - .window("Slider examples") - .opened(run) - .position([20.0, 20.0], Condition::Appearing) - .size([700.0, 80.0], Condition::Appearing) - .resizable(false); - w.build(|| { - let mut clicked = false; - clicked |= ui.radio_button("Example 1: Basic sliders", &mut state.example, 1); - clicked |= ui.radio_button("Example 2: Slider arrays", &mut state.example, 2); - if clicked { - state.reset(); - } - }); -} - -fn example_1(ui: &Ui, state: &mut State) { - let w = ui - .window("Example 1: Basic sliders") - .size([700.0, 340.0], Condition::Appearing) - .position([20.0, 120.0], Condition::Appearing); - w.build(|| { - ui.text("All of the following data types are supported:"); - ui.text("Signed: i8 i16 i32 i64"); - ui.text("Unsigned: u8 u16 u32 u64"); - ui.text("Floats: f32 f64"); - - // Full ranges can be specified with Rust's `::MIN/MAX` constants - ui.slider("u8 value", u8::MIN, u8::MAX, &mut state.u8_value); - - // However for larger data-types, it's usually best to specify - // a much smaller range. The following slider is hard to use. - ui.slider("Full range f32 value", f32::MIN/2.0, f32::MAX/2.0, &mut state.f32_value); - // Note the `... / 2.0` - anything larger is not supported by - // the upstream C++ library - ui.text("Note that for 32-bit/64-bit types, sliders are always limited to half of the natural type range!"); - - // Most of the time, it's best to specify the range - ui.separator(); - ui.text("Slider range can be limited:"); - ui.slider("i32 value with range", -999, 999, &mut state.i32_value); - ui.slider("f32 value", -10.0, 10.0, &mut state.f32_value); - - ui.separator(); - ui.text("Value formatting can be customized with a C-style printf string:"); - ui.slider_config("f64 value with custom formatting", -999_999_999.0, 999_999_999.0).display_format("%09.0f").build(&mut state.f64_formatted); - - // The display format changes the increments the slider operates in: - ui.slider_config("f32 with %.01f", 0.0, 1.0).display_format("%.01f").build(&mut state.f32_value); - ui.slider_config("Same f32 with %.05f", 0.0, 1.0).display_format("%.05f").build(&mut state.f32_value); - - ui.separator(); - ui.text("Vertical sliders require a size parameter but otherwise work in a similar way:"); - VerticalSlider::new("vertical\nu8 value", [50.0, 50.0], u8::MIN, u8::MAX) - .build(ui, &mut state.u8_value); - }); -} - -fn example_2(ui: &Ui, state: &mut State) { - let w = ui - .window("Example 2: Slider arrays") - .size([700.0, 260.0], Condition::Appearing) - .position([20.0, 120.0], Condition::Appearing); - w.build(|| { - ui.text("You can easily build a slider group from an array of values:"); - ui.slider_config("[u8; 4]", 0, u8::MAX) - .build_array(&mut state.array); - - ui.text("You don't need to use arrays with known length; arbitrary slices can be used:"); - let slice: &mut [u8] = &mut state.array[1..=2]; - ui.slider_config("subslice", 0, u8::MAX).build_array(slice); - }); -} - -#[derive(Default)] -struct State { - example: u32, - i32_value: i32, - u8_value: u8, - f32_value: f32, - f64_formatted: f64, - array: [u8; 4], -} - -impl State { - fn reset(&mut self) {} -} diff --git a/imgui-examples/examples/support/clipboard.rs b/imgui-examples/examples/support/clipboard.rs deleted file mode 100644 index dd74d06..0000000 --- a/imgui-examples/examples/support/clipboard.rs +++ /dev/null @@ -1,18 +0,0 @@ -use copypasta::{ClipboardContext, ClipboardProvider}; -use imgui::ClipboardBackend; - -pub struct ClipboardSupport(pub ClipboardContext); - -pub fn init() -> Option { - ClipboardContext::new().ok().map(ClipboardSupport) -} - -impl ClipboardBackend for ClipboardSupport { - fn get(&mut self) -> Option { - self.0.get_contents().ok() - } - fn set(&mut self, text: &str) { - // ignore errors? - let _ = self.0.set_contents(text.to_owned()); - } -} diff --git a/imgui-examples/examples/support/mod.rs b/imgui-examples/examples/support/mod.rs deleted file mode 100644 index 8a730ab..0000000 --- a/imgui-examples/examples/support/mod.rs +++ /dev/null @@ -1,164 +0,0 @@ -use glium::glutin::surface::WindowSurface; -use glium::{Display, Surface}; -use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui}; -use imgui_glium_renderer::Renderer; -use imgui_winit_support::winit::dpi::LogicalSize; -use imgui_winit_support::winit::event::{Event, WindowEvent}; -use imgui_winit_support::winit::event_loop::EventLoop; -use imgui_winit_support::winit::window::WindowBuilder; -use imgui_winit_support::{HiDpiMode, WinitPlatform}; -use std::path::Path; -use std::time::Instant; - -mod clipboard; - -pub const FONT_SIZE: f32 = 13.0; - -#[allow(dead_code)] // annoyingly, RA yells that this is unusued -pub fn simple_init(title: &str, run_ui: F) { - init_with_startup(title, |_, _, _| {}, run_ui); -} - -pub fn init_with_startup(title: &str, mut startup: FInit, mut run_ui: FUi) -where - FInit: FnMut(&mut Context, &mut Renderer, &Display) + 'static, - FUi: FnMut(&mut bool, &mut Ui) + 'static, -{ - let mut imgui = create_context(); - - let title = match Path::new(&title).file_name() { - Some(file_name) => file_name.to_str().unwrap(), - None => title, - }; - let event_loop = EventLoop::new().expect("Failed to create EventLoop"); - - let builder = WindowBuilder::new() - .with_title(title) - .with_inner_size(LogicalSize::new(1024, 768)); - let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new() - .set_window_builder(builder) - .build(&event_loop); - let mut renderer = Renderer::init(&mut imgui, &display).expect("Failed to initialize renderer"); - - if let Some(backend) = clipboard::init() { - imgui.set_clipboard_backend(backend); - } else { - eprintln!("Failed to initialize clipboard"); - } - - let mut platform = WinitPlatform::init(&mut imgui); - { - let dpi_mode = if let Ok(factor) = std::env::var("IMGUI_EXAMPLE_FORCE_DPI_FACTOR") { - // Allow forcing of HiDPI factor for debugging purposes - match factor.parse::() { - Ok(f) => HiDpiMode::Locked(f), - Err(e) => panic!("Invalid scaling factor: {}", e), - } - } else { - HiDpiMode::Default - }; - - platform.attach_window(imgui.io_mut(), &window, dpi_mode); - } - - let mut last_frame = Instant::now(); - - startup(&mut imgui, &mut renderer, &display); - - event_loop - .run(move |event, window_target| match event { - Event::NewEvents(_) => { - let now = Instant::now(); - imgui.io_mut().update_delta_time(now - last_frame); - last_frame = now; - } - Event::AboutToWait => { - platform - .prepare_frame(imgui.io_mut(), &window) - .expect("Failed to prepare frame"); - window.request_redraw(); - } - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - let ui = imgui.frame(); - - let mut run = true; - run_ui(&mut run, ui); - if !run { - window_target.exit(); - } - - let mut target = display.draw(); - target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); - platform.prepare_render(ui, &window); - let draw_data = imgui.render(); - renderer - .render(&mut target, draw_data) - .expect("Rendering failed"); - target.finish().expect("Failed to swap buffers"); - } - Event::WindowEvent { - event: WindowEvent::Resized(new_size), - .. - } => { - if new_size.width > 0 && new_size.height > 0 { - display.resize((new_size.width, new_size.height)); - } - platform.handle_event(imgui.io_mut(), &window, &event); - } - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => window_target.exit(), - event => { - platform.handle_event(imgui.io_mut(), &window, &event); - } - }) - .expect("EventLoop error"); -} - -/// Creates the imgui context -pub fn create_context() -> imgui::Context { - let mut imgui = Context::create(); - // Fixed font size. Note imgui_winit_support uses "logical - // pixels", which are physical pixels scaled by the devices - // scaling factor. Meaning, 13.0 pixels should look the same size - // on two different screens, and thus we do not need to scale this - // value (as the scaling is handled by winit) - imgui.fonts().add_font(&[ - FontSource::TtfData { - data: include_bytes!("../../../resources/Roboto-Regular.ttf"), - size_pixels: FONT_SIZE, - config: Some(FontConfig { - // As imgui-glium-renderer isn't gamma-correct with - // it's font rendering, we apply an arbitrary - // multiplier to make the font a bit "heavier". With - // default imgui-glow-renderer this is unnecessary. - rasterizer_multiply: 1.5, - // Oversampling font helps improve text rendering at - // expense of larger font atlas texture. - oversample_h: 4, - oversample_v: 4, - ..FontConfig::default() - }), - }, - FontSource::TtfData { - data: include_bytes!("../../../resources/mplus-1p-regular.ttf"), - size_pixels: FONT_SIZE, - config: Some(FontConfig { - // Oversampling font helps improve text rendering at - // expense of larger font atlas texture. - oversample_h: 4, - oversample_v: 4, - // Range of glyphs to rasterize - glyph_ranges: FontGlyphRanges::japanese(), - ..FontConfig::default() - }), - }, - ]); - imgui.set_ini_filename(None); - - imgui -} diff --git a/imgui-examples/examples/tables_api.rs b/imgui-examples/examples/tables_api.rs deleted file mode 100644 index be8718c..0000000 --- a/imgui-examples/examples/tables_api.rs +++ /dev/null @@ -1,210 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - let mut humans = vec![ - HumanData { - name: "Joonas", - favorite_number: 102, - favorite_fruit_maybe: "Dutch", - }, - HumanData { - name: "Thom", - favorite_number: 314, - favorite_fruit_maybe: "Rice", - }, - HumanData { - name: "Jack", - favorite_number: 611, - favorite_fruit_maybe: "Mangoes", - }, - ]; - - let mut t2_flags = TableFlags::REORDERABLE - | TableFlags::HIDEABLE - | TableFlags::RESIZABLE - | TableFlags::NO_BORDERS_IN_BODY; - - support::simple_init(file!(), move |_, ui| { - ui.window("Input text callbacks") - .size([800.0, 400.0], Condition::FirstUseEver) - .build(|| { - if let Some(_t) = ui.begin_table("Basic-Table", 3) { - // we must also call `next_row` here, because we declined - // to set up header rows. If we set up header rows ourselves, - // we will call `table_header_rows` instead, and if we use - // `begin_table_header`, then the initial call will be handled for us. - - ui.table_next_row(); - - // note you MUST call `next_column` at least to START - // Let's walk through a table like it's an iterator... - ui.table_set_column_index(0); - ui.text("x: 0, y: 0"); - - ui.table_next_column(); - ui.text("x: 1, y: 0"); - - ui.table_next_column(); - ui.text("x: 2, y: 0"); - - // // calling next column again will wrap us around to 0-1, - // // since we've exhausted our 3 columns. - ui.table_next_column(); - ui.text("x: 0, y: 1"); - - // // Let's do this manually now -- we can set each column ourselves... - ui.table_set_column_index(1); - ui.text("x: 1, y: 1"); - - ui.table_set_column_index(2); - ui.text("x: 2, y: 1"); - - // you CAN go back... - ui.table_set_column_index(1); - // however, you should call `new_line`, since otherwise - // we'd right on top of our `x: 1, y: 1` text. - ui.new_line(); - ui.text("our of order txt"); - } - - ui.separator(); - ui.text("Let's add some headers"); - if let Some(_t) = ui.begin_table_header( - "table-headers", - [ - TableColumnSetup::new("Name"), - TableColumnSetup::new("Age"), - TableColumnSetup::new("Favorite fruit"), - ], - ) { - // note that we DON'T have to call "table_next_row" here -- that's taken care - // of for us by `begin_table_header`, since it actually calls `table_headers_row` - - // but we DO need to call column! - // but that's fine, we'll use a loop - for i in 0..3 { - let names = ["Joonas", "Thom", "Jack"]; - let fruit = ["Dutch", "Rice", "Mangoes"]; - - ui.table_next_column(); - ui.text(names[i]); - - ui.table_next_column(); - ui.text((i * 9).to_string()); - - ui.table_next_column(); - ui.text(fruit[i]); - } - } - - ui.separator(); - ui.text("Let's do some context menus"); - ui.text( - "context menus are created, by default, from the flags passed\ - while making the table, or each row.\n\ - Notice how toggling these checkboxes changes the context menu.", - ); - - ui.checkbox_flags("Reorderable", &mut t2_flags, TableFlags::REORDERABLE); - ui.same_line(); - ui.checkbox_flags("Hideable", &mut t2_flags, TableFlags::HIDEABLE); - ui.same_line(); - ui.checkbox_flags("Resizable", &mut t2_flags, TableFlags::RESIZABLE); - - if let Some(_t) = ui.begin_table_header_with_flags( - "table-headers2", - [ - TableColumnSetup::new("Name"), - TableColumnSetup::new("Age"), - TableColumnSetup::new("Favorite fruit"), - ], - t2_flags, - ) { - // note that we DON'T have to call "table_next_row" here -- that's taken care - // of for us by `begin_table_header`, since it actually calls `table_headers_row` - - // but we DO need to call column! - // but that's fine, we'll use a loop - for i in 0..3 { - let names = ["Joonas", "Thom", "Jack"]; - let fruit = ["Dutch", "Rice", "Mangoes"]; - - ui.table_next_column(); - ui.text(names[i]); - - ui.table_next_column(); - ui.text((i * 9).to_string()); - - ui.table_next_column(); - ui.text(fruit[i]); - } - } - - ui.separator(); - - ui.text("Here's a table you can sort!"); - ui.text("Check the code to see the two methods of doing it."); - - if let Some(_t) = ui.begin_table_header_with_flags( - "table-headers3", - [ - TableColumnSetup::new("Name"), - TableColumnSetup::new("Favorite Number"), - TableColumnSetup::new("Favorite fruit"), - ], - TableFlags::SORTABLE, - ) { - if let Some(sort_data) = ui.table_sort_specs_mut() { - sort_data - .conditional_sort(|specs| HumanData::sort_humans(&mut humans, specs)); - - // Can also sort this other way... - // if sort_data.should_sort() { - // HumanData::sort_humans(&mut humans, sort_data.specs()); - // sort_data.set_sorted(); - // } - } - - for human in humans.iter() { - ui.table_next_column(); - ui.text(human.name); - - ui.table_next_column(); - ui.text(human.favorite_number.to_string()); - - ui.table_next_column(); - ui.text(human.favorite_fruit_maybe); - } - } - }); - }); -} -struct HumanData { - name: &'static str, - favorite_number: usize, - favorite_fruit_maybe: &'static str, -} - -impl HumanData { - pub fn sort_humans(humans: &mut [Self], specs: Specs<'_>) { - let spec = specs.iter().next().unwrap(); - if let Some(kind) = spec.sort_direction() { - match kind { - TableSortDirection::Ascending => match spec.column_idx() { - 0 => humans.sort_by_key(|h| h.name), - 1 => humans.sort_by_key(|h| h.favorite_number), - 2 => humans.sort_by_key(|h| h.favorite_fruit_maybe), - _ => unimplemented!(), - }, - TableSortDirection::Descending => match spec.column_idx() { - 0 => humans.sort_by_key(|h| std::cmp::Reverse(h.name)), - 1 => humans.sort_by_key(|h| std::cmp::Reverse(h.favorite_number)), - 2 => humans.sort_by_key(|h| std::cmp::Reverse(h.favorite_fruit_maybe)), - _ => unimplemented!(), - }, - } - } - } -} diff --git a/imgui-examples/examples/test_drawing_channels_split.rs b/imgui-examples/examples/test_drawing_channels_split.rs deleted file mode 100644 index 351b394..0000000 --- a/imgui-examples/examples/test_drawing_channels_split.rs +++ /dev/null @@ -1,37 +0,0 @@ -mod support; - -const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0]; -const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0]; - -fn main() { - support::simple_init(file!(), move |_, ui| { - let draw_list = ui.get_window_draw_list(); - // Will draw channel 0 first, then channel 1, whatever the order of - // the calls in the code. - // - // Here, we draw a red line on channel 1 then a white circle on - // channel 0. As a result, the red line will always appear on top of - // the white circle. - draw_list.channels_split(2, |channels| { - const RADIUS: f32 = 100.0; - let canvas_pos = ui.cursor_screen_pos(); - channels.set_current(1); - draw_list - .add_line( - canvas_pos, - [canvas_pos[0] + RADIUS, canvas_pos[1] + RADIUS], - RED, - ) - .thickness(5.0) - .build(); - - channels.set_current(0); - let center = [canvas_pos[0] + RADIUS, canvas_pos[1] + RADIUS]; - draw_list - .add_circle(center, RADIUS, WHITE) - .thickness(10.0) - .num_segments(50) - .build(); - }); - }); -} diff --git a/imgui-examples/examples/test_window.rs b/imgui-examples/examples/test_window.rs deleted file mode 100644 index 2a7e4ce..0000000 --- a/imgui-examples/examples/test_window.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod support; - -fn main() { - support::simple_init(file!(), move |run, ui| ui.show_demo_window(run)); -} diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs deleted file mode 100644 index 0a7e6e4..0000000 --- a/imgui-examples/examples/test_window_impl.rs +++ /dev/null @@ -1,1308 +0,0 @@ -use imgui::*; - -mod support; - -struct State { - show_app_main_menu_bar: bool, - show_app_console: bool, - show_app_log: bool, - show_app_layout: bool, - show_app_property_editor: bool, - show_app_long_text: bool, - show_app_auto_resize: bool, - show_app_constrained_resize: bool, - show_app_fixed_overlay: bool, - show_app_manipulating_window_title: bool, - show_app_custom_rendering: bool, - show_app_style_editor: bool, - show_app_metrics: bool, - show_app_about: bool, - no_titlebar: bool, - no_resize: bool, - no_move: bool, - no_scrollbar: bool, - no_collapse: bool, - no_menu: bool, - no_close: bool, - wrap_width: f32, - buf: String, - item: usize, - item2: usize, - item3: i32, - text: String, - text_with_hint: String, - text_multiline: String, - i0: i32, - u0: u64, - d0: f64, - f0: f32, - vec2f: [f32; 2], - vec3f: [f32; 3], - vec2i: [i32; 2], - vec3i: [i32; 3], - col1: [f32; 3], - col2: [f32; 4], - selected_fish: Option, - selected_fish2: Option, - auto_resize_state: AutoResizeState, - file_menu: FileMenuState, - radio_button: i32, - color_edit: ColorEditState, - custom_rendering: CustomRenderingState, - dont_ask_me_next_time: bool, - stacked_modals_item: usize, - stacked_modals_color: [f32; 4], - app_log: Vec, - filter: imgui::TextFilter, - - tabs: TabState, -} - -impl Default for State { - fn default() -> Self { - let mut buf = String::with_capacity(32); - buf.push_str("日本語"); - let mut text = String::with_capacity(128); - text.push_str("Hello, world!"); - let text_with_hint = String::with_capacity(128); - let mut text_multiline = String::with_capacity(128); - text_multiline.push_str("Hello, world!\nMultiline"); - State { - show_app_main_menu_bar: false, - show_app_console: false, - show_app_log: false, - show_app_layout: false, - show_app_property_editor: false, - show_app_long_text: false, - show_app_auto_resize: false, - show_app_fixed_overlay: false, - show_app_constrained_resize: false, - show_app_manipulating_window_title: false, - show_app_custom_rendering: false, - show_app_style_editor: false, - show_app_metrics: false, - show_app_about: false, - no_titlebar: false, - no_resize: false, - no_move: false, - no_scrollbar: false, - no_collapse: false, - no_menu: false, - no_close: false, - wrap_width: 200.0, - buf, - item: 0, - item2: 0, - item3: 0, - text, - text_with_hint, - text_multiline, - i0: 123, - u0: 1234, - f0: 0.001, - d0: 0.0001, - vec2f: [0.10, 0.20], - vec3f: [0.10, 0.20, 0.30], - vec2i: [10, 20], - vec3i: [10, 20, 30], - col1: [1.0, 0.0, 0.2], - col2: [0.4, 0.7, 0.0, 0.5], - selected_fish: None, - selected_fish2: None, - auto_resize_state: Default::default(), - file_menu: Default::default(), - radio_button: 0, - color_edit: ColorEditState::default(), - custom_rendering: Default::default(), - dont_ask_me_next_time: false, - stacked_modals_item: 0, - stacked_modals_color: [0.4, 0.7, 0.0, 0.5], - app_log: Vec::new(), - filter: TextFilter::new(String::from("Test")), - tabs: TabState::default(), - } - } -} - -struct TabState { - // flags for the advanced tab example - reorderable: bool, - autoselect: bool, - listbutton: bool, - noclose_middlebutton: bool, - fitting_resizedown: bool, - fitting_scroll: bool, - - // opened state for tab items - artichoke_tab: bool, - beetroot_tab: bool, - celery_tab: bool, - daikon_tab: bool, -} - -impl Default for TabState { - fn default() -> Self { - Self { - reorderable: true, - autoselect: false, - listbutton: false, - noclose_middlebutton: false, - fitting_resizedown: true, - fitting_scroll: false, - - artichoke_tab: true, - beetroot_tab: true, - celery_tab: true, - daikon_tab: true, - } - } -} - -struct ColorEditState { - color: [f32; 4], - hdr: bool, - alpha_preview: bool, - alpha_half_preview: bool, - options_menu: bool, - alpha: bool, - alpha_bar: bool, - side_preview: bool, - ref_color: bool, - ref_color_v: [f32; 4], -} - -impl Default for ColorEditState { - fn default() -> Self { - ColorEditState { - color: [114.0 / 255.0, 144.0 / 255.0, 154.0 / 255.0, 200.0 / 255.0], - hdr: false, - alpha_preview: true, - alpha_half_preview: false, - options_menu: true, - alpha: true, - alpha_bar: true, - side_preview: true, - ref_color: false, - ref_color_v: [1.0, 0.0, 1.0, 0.5], - } - } -} - -struct FileMenuState { - enabled: bool, - f: f32, - n: usize, - b: bool, -} - -impl Default for FileMenuState { - fn default() -> Self { - FileMenuState { - enabled: true, - f: 0.5, - n: 0, - b: true, - } - } -} - -struct AutoResizeState { - lines: i32, -} - -impl Default for AutoResizeState { - fn default() -> Self { - AutoResizeState { lines: 10 } - } -} - -struct CustomRenderingState { - sz: f32, - col: [f32; 3], - points: Vec<[f32; 2]>, - adding_line: bool, -} - -impl Default for CustomRenderingState { - fn default() -> Self { - CustomRenderingState { - sz: 36.0, - col: [1.0, 1.0, 0.4], - points: vec![], - adding_line: false, - } - } -} - -fn main() { - let mut state = State::default(); - - support::simple_init(file!(), move |run, ui| { - show_test_window(ui, &mut state, run) - }); -} - -fn show_help_marker(ui: &Ui, desc: &str) { - ui.text_disabled("(?)"); - if ui.is_item_hovered() { - ui.tooltip(|| { - ui.text(desc); - }); - } -} - -fn show_user_guide(ui: &Ui) { - ui.bullet_text("Double-click on title bar to collapse window."); - ui.bullet_text("Click and drag on lower right corner to resize window."); - ui.bullet_text("Click and drag on any empty space to move window."); - ui.bullet_text("Mouse Wheel to scroll."); - // TODO: check font_allow_user_scaling - ui.bullet_text("TAB/SHIFT+TAB to cycle through keyboard editable fields."); - ui.bullet_text("CTRL+Click on a slider or drag box to input text."); - ui.bullet_text( - "While editing text: -- Hold SHIFT or use mouse to select text -- CTRL+Left/Right to word jump -- CTRL+A or double-click to select all -- CTRL+X,CTRL+C,CTRL+V clipboard -- CTRL+Z,CTRL+Y undo/redo -- ESCAPE to revert -- You can apply arithmetic operators +,*,/ on numerical values. - Use +- to subtract.\n", - ); -} - -fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { - if state.show_app_main_menu_bar { - show_example_app_main_menu_bar(ui, state) - } - if state.show_app_auto_resize { - show_example_app_auto_resize( - ui, - &mut state.auto_resize_state, - &mut state.show_app_auto_resize, - ); - } - if state.show_app_fixed_overlay { - show_example_app_fixed_overlay(ui, &mut state.show_app_fixed_overlay); - } - if state.show_app_manipulating_window_title { - show_example_app_manipulating_window_title(ui); - } - if state.show_app_metrics { - ui.show_metrics_window(&mut state.show_app_metrics); - } - if state.show_app_style_editor { - ui.window("Style Editor") - .opened(&mut state.show_app_style_editor) - .build(|| ui.show_default_style_editor()); - } - if state.show_app_about { - ui.window("About ImGui") - .always_auto_resize(true) - .opened(&mut state.show_app_about) - .build(|| { - ui.text(format!("dear imgui, {}", imgui::dear_imgui_version())); - ui.separator(); - ui.text("By Omar Cornut and all github contributors."); - ui.text( - "ImGui is licensed under the MIT License, see LICENSE for more \ - information.", - ); - }); - } - - if state.show_app_custom_rendering { - show_example_app_custom_rendering( - ui, - &mut state.custom_rendering, - &mut state.show_app_custom_rendering, - ); - } - - if state.show_app_log { - show_app_log(ui, &mut state.app_log); - } - - let mut window = ui - .window("ImGui Demo") - .title_bar(!state.no_titlebar) - .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], Condition::FirstUseEver); - if !state.no_close { - window = window.opened(opened) - } - window.build(|| { - let _w = ui.push_item_width(-140.0); - ui.text(format!("dear imgui says hello. ({})", imgui::dear_imgui_version())); - if let Some(_menu_bar) = ui.begin_menu_bar() { - if let Some(menu) = ui.begin_menu("Menu") { - show_example_menu_file(ui, &mut state.file_menu); - menu.end(); - } - if let Some(_t) = ui.begin_menu("Examples") { - ui.menu_item_config("Main menu bar").build_with_ref(&mut state.show_app_main_menu_bar); - ui.menu_item_config("Console").build_with_ref(&mut state.show_app_console); - ui.menu_item_config("Log").build_with_ref(&mut state.show_app_log); - ui.menu_item_config("Simple layout").build_with_ref(&mut state.show_app_layout); - ui.menu_item_config("Property editor").build_with_ref(&mut state.show_app_property_editor); - ui.menu_item_config("Long text display").build_with_ref(&mut state.show_app_long_text); - ui.menu_item_config("Auto-resizing window").build_with_ref(&mut state.show_app_auto_resize); - ui.menu_item_config("Constrained-resizing window").build_with_ref(&mut state.show_app_constrained_resize); - ui.menu_item_config("Simple overlay").build_with_ref(&mut state.show_app_fixed_overlay); - ui.menu_item_config("Manipulating window title").build_with_ref(&mut state.show_app_manipulating_window_title); - ui.menu_item_config("Custom Rendering").build_with_ref(&mut state.show_app_custom_rendering); - } - if let Some(_menu) = ui.begin_menu("Help") { - ui.menu_item_config("Metrics").build_with_ref(&mut state.show_app_metrics); - ui.menu_item_config("Style Editor").build_with_ref(&mut state.show_app_style_editor); - ui.menu_item_config("About ImGui").build_with_ref(&mut state.show_app_about); - } - } - ui.spacing(); - if CollapsingHeader::new("Help").build(ui) { - ui.text_wrapped( - "This window is being created by the show_test_window() \ - function. Please refer to the code for programming \ - reference.\n\nUser Guide:" - ); - show_user_guide(ui); - } - - if CollapsingHeader::new("Window options").build(ui) { - ui.checkbox("No titlebar", &mut state.no_titlebar); - ui.same_line_with_pos(150.0); - ui.checkbox("No scrollbar", &mut state.no_scrollbar); - ui.same_line_with_pos(300.0); - ui.checkbox("No menu", &mut state.no_menu); - ui.checkbox("No move", &mut state.no_move); - ui.same_line_with_pos(150.0); - ui.checkbox("No resize", &mut state.no_resize); - ui.same_line_with_pos(300.0); - ui.checkbox("No collapse", &mut state.no_collapse); - ui.checkbox("No close", &mut state.no_close); - - if let Some(_t) = ui.tree_node("Style") { - ui.show_default_style_editor(); - } - } - if CollapsingHeader::new("Widgets").build(ui) { - if let Some(_t) = ui.tree_node("Tree") { - let num_child = 4; - for i in 0..num_child { - if let Some(_t) = ui.tree_node(format!("Child {}", i)) { - ui.text("blah blah"); - ui.same_line(); - if ui.small_button("print") { - println!("Child {} pressed", i); - } - } - } - - { - let tree_node_stack = ui.tree_node_config("##HideTreeNodeLabel") - .allow_item_overlap(true) - .push(); - ui.same_line(); - if ui.small_button(format!("Child {} is a button", num_child)) { - println!("TreeNode Button pressed."); - } - - if tree_node_stack.is_some() { - ui.text("blah blah") - } - } - } - - if let Some(_t) = ui.tree_node("Bullets") { - ui.bullet_text("Bullet point 1"); - ui.bullet_text("Bullet point 2\nOn multiple lines"); - ui.bullet(); - ui.text("Bullet point 3 (two calls)"); - - ui.bullet(); - ui.small_button("Button"); - } - - if let Some(_t) = ui.tree_node("Colored text") { - ui.text_colored([1.0, 0.0, 1.0, 1.0], "Pink"); - ui.text_colored([1.0, 1.0, 0.0, 1.0], "Yellow"); - ui.text_disabled("Disabled"); - } - - if let Some(_t) = ui.tree_node("Multi-line text") { - ui.input_text_multiline( - "multiline", - &mut state.text_multiline, - [300., 100.], - ).build(); - } - - if let Some(_t) = ui.tree_node("Word wrapping") { - ui.text_wrapped( - "This text should automatically wrap on the edge of \ - the window.The current implementation for text \ - wrapping follows simple rules suitable for English \ - and possibly other languages." - ); - ui.spacing(); - - ui.slider_config("Wrap width", -20.0, 600.0) - .display_format("%.0f") - .build(&mut state.wrap_width); - - ui.text("Test paragraph 1:"); - // TODO - - ui.text("Test paragraph 2:"); - // TODO - } - - if let Some(_t) = ui.tree_node("UTF-8 Text") { - ui.text_wrapped( - "CJK text will only appear if the font was loaded \ - with theappropriate CJK character ranges. Call \ - io.Font->LoadFromFileTTF()manually to load extra \ - character ranges." - ); - - ui.text("Hiragana: かきくけこ (kakikukeko)"); - ui.text("Kanjis: 日本語 (nihongo)"); - ui.input_text("UTF-8 input", &mut state.buf) - .build(); - } - - ui.radio_button("radio a", &mut state.radio_button, 0); - ui.same_line(); - ui.radio_button("radio b", &mut state.radio_button, 1); - ui.same_line(); - ui.radio_button("radio c", &mut state.radio_button, 2); - - ui.separator(); - ui.label_text("label", "Value"); - ui.combo_simple_string("combo", - &mut state.item, - &[ - "aaaa", - "bbbb", - "cccc", - "dddd", - "eeee", - ]); - let items = [ - "AAAA", - "BBBB", - "CCCC", - "DDDD", - "EEEE", - "FFFF", - "GGGG", - "HHHH", - "IIII", - "JJJJ", - "KKKK", - ]; - ui.combo_simple_string("combo scroll", &mut state.item2, &items); - ui.list_box("list", &mut state.item3, &items, 8); - - - let names = [ - "Bream", - "Haddock", - "Mackerel", - "Pollock", - "Tilefish", - ]; - - ListBox::new("selectables list").build(ui, || { - for (index, name) in names.iter().enumerate() { - let selected = matches!(state.selected_fish2, Some(i) if i == index ); - if ui.selectable_config(name).selected(selected).build() { - state.selected_fish2 = Some(index); - } - } - }); - - let last_size = ui.item_rect_size(); - ListBox::new("selectable list 2").size([0.0, last_size[1] * 0.66]).build(ui, || { - for (index, name) in names.iter().enumerate() { - let selected = matches!(state.selected_fish2, Some(i) if i == index ); - if ui.selectable_config(name).selected(selected).build() { - state.selected_fish2 = Some(index); - } - } - }); - - ui.input_text("input text", &mut state.text) - .build(); - ui.input_text("input text with hint", &mut state.text_with_hint) - .hint("enter text here") - .build(); - ui.input_int("input int", &mut state.i0).build(); - // Drag::new("drag int").build(ui, &mut state.i0); - ui.input_float("input float", &mut state.f0) - .step(0.01) - .step_fast(1.0) - .build(); - Drag::new("drag float").range(-1.0, 1.0).speed(0.001).build(ui, &mut state.f0); - ui.input_float3("input float3", &mut state.vec3f) - .build(); - - ui.color_edit3("color 1", &mut state.col1); - ui.color_edit4("color 2", &mut state.col2); - - ui.input_scalar("input scalar i64", &mut state.u0).build(); - ui.input_scalar("input scalar f64", &mut state.d0).build(); - ui.input_scalar_n("input scalar int array", &mut state.vec3i).build(); - ui.input_scalar_n("input scalar float array", &mut state.vec3f).build(); - - if let Some(_t) = ui.tree_node("Multi-component Widgets") { - ui.input_float2("input float2", &mut state.vec2f) - .build(); - ui.input_int2("input int2", &mut state.vec2i) - .build(); - ui.spacing(); - - ui.input_float3("input float3", &mut state.vec3f) - .build(); - ui.input_int3("input int3", &mut state.vec3i) - .build(); - ui.spacing(); - }; - - if let Some(_t) = ui.tree_node("Color/Picker Widgets") { - let s = &mut state.color_edit; - ui.checkbox("With HDR", &mut s.hdr); - ui.same_line(); - show_help_marker( - ui, - "Currently all this does is to lift the 0..1 \ - limits on dragging widgets.", - ); - - ui.checkbox("With Alpha Preview", &mut s.alpha_preview); - ui.checkbox( - "With Half Alpha Preview", - &mut s.alpha_half_preview, - ); - ui.checkbox("With Options Menu", &mut s.options_menu); - ui.same_line(); - show_help_marker( - ui, - "Right-click on the individual color widget to \ - show options.", - ); - let misc_flags = { - let mut f = ColorEditFlags::empty(); - f.set(ColorEditFlags::HDR, s.hdr); - f.set(ColorEditFlags::ALPHA_PREVIEW_HALF, s.alpha_half_preview); - if !s.alpha_half_preview { - f.set(ColorEditFlags::ALPHA_PREVIEW, s.alpha_preview); - } - f.set(ColorEditFlags::NO_OPTIONS, !s.options_menu); - f - }; - - ui.text("Color widget:"); - ui.same_line(); - show_help_marker( - ui, - "Click on the colored square to open a color picker. -CTRL+click on individual component to input value.\n", - ); - ui.color_edit4_config("MyColor##1", &mut s.color) - .flags(misc_flags) - .alpha(false) - .build(); - - ui.text("Color widget HSV with Alpha:"); - ui.color_edit4_config("MyColor##2", &mut s.color) - .flags(misc_flags) - .input_mode(ColorEditInputMode::HSV) - .build(); - - ui.text("Color widget with Float Display:"); - ui.color_edit4_config("MyColor##2f", &mut s.color) - .flags(misc_flags) - .format(ColorFormat::Float) - .build(); - - ui.text("Color button with Picker:"); - ui.same_line(); - show_help_marker( - ui, - "With the inputs(false) function you can hide all \ - the slider/text inputs.\n \ - With the label(false) function you can pass a non-empty label which \ - will only be used for the tooltip and picker popup.", - ); - ui.color_edit4_config("MyColor##3", &mut s.color) - .flags(misc_flags) - .inputs(false) - .label(false) - .build(); - - ui.text("Color picker:"); - ui.checkbox("With Alpha", &mut s.alpha); - ui.checkbox("With Alpha Bar", &mut s.alpha_bar); - ui.checkbox("With Side Preview", &mut s.side_preview); - if s.side_preview { - ui.same_line(); - ui.checkbox("With Ref Color", &mut s.ref_color); - if s.ref_color { - ui.same_line(); - ui.color_edit4_config("##RefColor", &mut s.ref_color_v) - .flags(misc_flags) - .inputs(false) - .build(); - } - } - let mut b = ui.color_picker4_config - ("MyColor##4", &mut s.color) - .flags(misc_flags) - .alpha(s.alpha) - .alpha_bar(s.alpha_bar) - .side_preview(s.side_preview) - .display_rgb(true); - - if s.ref_color { - b = b.reference_color(s.ref_color_v) - } - b.build(); - } - } - - if CollapsingHeader::new("Layout").build(ui) { - if let Some(_t) = ui.tree_node("Tabs") { - if let Some(_t) = ui.tree_node("Basic") { - TabBar::new("basictabbar").build(ui, || { - TabItem::new("Avocado").build(ui, || { - ui.text("This is the Avocado tab!"); - ui.text("blah blah blah blah blah"); - }); - TabItem::new("Broccoli").build(ui, || { - ui.text("This is the Broccoli tab!"); - ui.text("blah blah blah blah blah"); - }); - TabItem::new("Cucumber").build(ui, || { - ui.text("This is the Cucumber tab!"); - ui.text("blah blah blah blah blah"); - }); - }); - } - - if let Some(_t) = ui.tree_node("Advanced & Close button") { - - ui.separator(); - let s = &mut state.tabs; - - ui.checkbox("ImGuiTabBarFlags_Reorderable", &mut s.reorderable); - ui.checkbox("ImGuiTabBarFlags_AutoSelectNewTabs", &mut s.autoselect); - ui.checkbox("ImGuiTabBarFlags_TabListPopupButton", &mut s.listbutton); - ui.checkbox("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &mut s.noclose_middlebutton); - if ui.checkbox("ImGuiTabBarFlags_FittingPolicyResizeDown", &mut s.fitting_resizedown) { - s.fitting_scroll = !s.fitting_resizedown; - } - if ui.checkbox("ImGuiTabBarFlags_FittingPolicyScroll", &mut s.fitting_scroll) { - s.fitting_resizedown = !s.fitting_scroll; - } - let style = ui.push_style_var(StyleVar::FramePadding([0.0, 0.0])); - ui.checkbox("Artichoke", &mut s.artichoke_tab); - ui.same_line(); - ui.checkbox("Beetroot", &mut s.beetroot_tab); - ui.same_line(); - ui.checkbox("Celery", &mut s.celery_tab); - ui.same_line(); - ui.checkbox("Daikon", &mut s.daikon_tab); - style.pop(); - - let flags = { - let mut f = TabBarFlags::empty(); - f.set(TabBarFlags::REORDERABLE, s.reorderable); - f.set(TabBarFlags::AUTO_SELECT_NEW_TABS, s.autoselect); - f.set(TabBarFlags::TAB_LIST_POPUP_BUTTON, s.listbutton); - f.set(TabBarFlags::NO_CLOSE_WITH_MIDDLE_MOUSE_BUTTON, s.noclose_middlebutton); - f.set(TabBarFlags::FITTING_POLICY_RESIZE_DOWN, s.fitting_resizedown); - f.set(TabBarFlags::FITTING_POLICY_SCROLL, s.fitting_scroll); - f - }; - - TabBar::new("tabbar").flags(flags).build(ui, || { - TabItem::new("Artichoke").opened(&mut s.artichoke_tab).build(ui, || { - ui.text("This is the Artichoke tab!"); - }); - TabItem::new("Beetroot").opened(&mut s.beetroot_tab).build(ui, || { - ui.text("This is the Beetroot tab!"); - }); - TabItem::new("Celery").opened(&mut s.celery_tab).build(ui, || { - ui.text("This is the Celery tab!"); - }); - TabItem::new("Daikon").opened(&mut s.daikon_tab).build(ui, || { - ui.text("This is the Daikon tab!"); - }); - }); - - } - } - } - - if CollapsingHeader::new("Filtering").build(ui) { - ui.text_wrapped( - "Filter usage:\n\ - \"\" display all lines\n\ - \"xxx\" display lines containing \"xxx\"\n\ - \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n\ - \"-xxx\" hide lines containing \"xxx\"" - ); - - state.filter.draw(); - let lines = ["aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world!"]; - - ui.same_line(); - if ui.button("Clear##clear_filter") { - state.filter.clear(); - } - - for i in lines.iter() { - if state.filter.pass_filter(i) { - ui.bullet_text(i); - } - } - } - - if CollapsingHeader::new("Popups & Modal windows").build(ui) { - if let Some(_t) = ui.tree_node("Popups") { - ui.text_wrapped( - "When a popup is active, it inhibits interacting \ - with windows that are behind the popup. Clicking \ - outside the popup closes it." - ); - let names = [ - "Bream", - "Haddock", - "Mackerel", - "Pollock", - "Tilefish", - ]; - if ui.small_button("Select..") { - ui.open_popup("select"); - } - ui.same_line(); - ui.text(match state.selected_fish { - Some(index) => names[index], - None => "", - }); - ui.popup("select", || { - ui.text("Aquarium"); - ui.separator(); - for (index, name) in names.iter().enumerate() { - if ui.selectable(name) { - state.selected_fish = Some(index); - } - } - }); - } - - if let Some(_t) = ui.tree_node("Modals") { - ui.text_wrapped( - "Modal windows are like popups but the user cannot close \ - them by clicking outside the window." - ); - - if ui.button("Delete..") { - ui.open_popup("Delete?"); - } - ui.modal_popup_config("Delete?").always_auto_resize(true).build(|| { - ui.text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); - ui.separator(); - let style = ui.push_style_var(StyleVar::FramePadding([0.0, 0.0])); - ui.checkbox("Don't ask me next time", &mut state.dont_ask_me_next_time); - - if ui.button_with_size("OK", [120.0, 0.0]) { - ui.close_current_popup(); - } - ui.same_line(); - if ui.button_with_size("Cancel", [120.0, 0.0]) { - ui.close_current_popup(); - } - style.pop(); - }); - - if ui.button("Stacked modals..") { - ui.open_popup("Stacked 1"); - } - ui.modal_popup_config("Stacked 1").build(|| { - ui.text( - "Hello from Stacked The First\n\ - Using style[StyleColor::ModalWindowDarkening] for darkening." - ); - - let items = &["aaaa", "bbbb", "cccc", "dddd", "eeee"]; - ui.combo_simple_string("Combo", &mut state.stacked_modals_item, items); - - ui.color_edit4_config("color", &mut state.stacked_modals_color).build(); - - if ui.button("Add another modal..") { - ui.open_popup("Stacked 2") ; - } - ui.modal_popup_config("Stacked 2").build(|| { - ui.text("Hello from Stacked The Second"); - if ui.button("Close") { - ui.close_current_popup(); - } - }); - - if ui.button("Close") { - ui.close_current_popup(); - } - }); - } - } - }); -} - -fn show_example_app_main_menu_bar(ui: &Ui, state: &mut State) { - if let Some(menu_bar) = ui.begin_main_menu_bar() { - if let Some(menu) = ui.begin_menu("File") { - show_example_menu_file(ui, &mut state.file_menu); - menu.end(); - } - if let Some(menu) = ui.begin_menu("Edit") { - ui.menu_item_config("Undo").shortcut("CTRL+Z").build(); - ui.menu_item_config("Redo") - .shortcut("CTRL+Y") - .enabled(false) - .build(); - ui.separator(); - ui.menu_item_config("Cut").shortcut("CTRL+X").build(); - ui.menu_item_config("Copy").shortcut("CTRL+C").build(); - ui.menu_item_config("Paste").shortcut("CTRL+V").build(); - menu.end(); - } - menu_bar.end(); - } -} - -fn show_example_menu_file(ui: &Ui, state: &mut FileMenuState) { - ui.menu_item_config("(dummy_menu)").enabled(false).build(); - ui.menu_item("New"); - ui.menu_item_config("Open").shortcut("Ctrl+O").build(); - if let Some(_menu) = ui.begin_menu("Open Recent") { - ui.menu_item("fish_hat.c"); - ui.menu_item("fish_hat.inl"); - ui.menu_item("fish_hat.h"); - if let Some(menu) = ui.begin_menu("More..") { - ui.menu_item("Hello"); - ui.menu_item("Sailor"); - - if let Some(_menu) = ui.begin_menu("Recurse..") { - show_example_menu_file(ui, state); - menu.end(); - } - } - } - ui.menu_item_config("Save").shortcut("Ctrl+S").build(); - ui.menu_item("Save As.."); - ui.separator(); - if let Some(_menu) = ui.begin_menu("Options") { - ui.menu_item_config("Enabled") - .build_with_ref(&mut state.enabled); - - ui.child_window("child") - .size([0.0, 60.0]) - .border(true) - .build(|| { - for i in 0..10 { - ui.text(format!("Scrolling Text {}", i)); - } - }); - ui.slider("Value", 0.0, 1.0, &mut state.f); - - ui.input_float("Input", &mut state.f).step(0.1).build(); - let items = ["Yes", "No", "Maybe"]; - ui.combo_simple_string("Combo", &mut state.n, &items); - ui.checkbox("Check", &mut state.b); - } - if let Some(_menu) = ui.begin_menu("Colors") { - for &col in StyleColor::VARIANTS.iter() { - ui.menu_item(format!("{:?}", col)); - } - } - assert!(ui.begin_menu_with_enabled("Disabled", false).is_none()); - ui.menu_item_config("Checked").selected(true).build(); - ui.menu_item_config("Quit").shortcut("Alt+F4").build(); -} - -fn show_example_app_auto_resize(ui: &Ui, state: &mut AutoResizeState, opened: &mut bool) { - ui.window("Example: Auto-resizing window") - .opened(opened) - .always_auto_resize(true) - .build(|| { - ui.text( - "Window will resize every-ui to the size of its content. -Note that you probably don't want to query the window size to -output your content because that would create a feedback loop.", - ); - ui.slider("Number of lines", 1, 20, &mut state.lines); - for i in 0..state.lines { - ui.text(format!("{:2$}This is line {}", "", i, i as usize * 4)); - } - }); -} - -fn show_example_app_fixed_overlay(ui: &Ui, opened: &mut bool) { - const DISTANCE: f32 = 10.0; - let window_pos = [DISTANCE, DISTANCE]; - let style = ui.push_style_color(StyleColor::WindowBg, [0.0, 0.0, 0.0, 0.3]); - ui.window("Example: Fixed Overlay") - .opened(opened) - .position(window_pos, Condition::Always) - .title_bar(false) - .resizable(false) - .always_auto_resize(true) - .movable(false) - .save_settings(false) - .build(|| { - ui.text( - "Simple overlay\nin the corner of the screen.\n(right-click to change position)", - ); - ui.separator(); - let mouse_pos = ui.io().mouse_pos; - ui.text(format!( - "Mouse Position: ({:.1},{:.1})", - mouse_pos[0], mouse_pos[1] - )); - }); - style.pop(); -} - -fn show_example_app_manipulating_window_title(ui: &Ui) { - ui.window("Same title as another window##1") - .position([100.0, 100.0], Condition::FirstUseEver) - .build(|| { - ui.text( - "This is window 1. -My title is the same as window 2, but my identifier is unique.", - ); - }); - ui.window("Same title as another window##2") - .position([100.0, 200.0], Condition::FirstUseEver) - .build(|| { - ui.text( - "This is window 2. -My title is the same as window 1, but my identifier is unique.", - ); - }); - let chars = ['|', '/', '-', '\\']; - let ch_idx = (ui.time() / 0.25) as usize & 3; - let num = ui.frame_count(); // The C++ version uses rand() here - let title = format!("Animated title {} {}###AnimatedTitle", chars[ch_idx], num); - ui.window(title) - .position([100.0, 300.0], Condition::FirstUseEver) - .build(|| ui.text("This window has a changing title")); -} - -fn show_example_app_custom_rendering(ui: &Ui, state: &mut CustomRenderingState, opened: &mut bool) { - ui.window("Example: Custom rendering") - .size([350.0, 560.0], Condition::FirstUseEver) - .opened(opened) - .build(|| { - ui.text("Primitives"); - // TODO: Add DragFloat to change value of sz - ui.color_edit3("Color", &mut state.col); - let draw_list = ui.get_window_draw_list(); - let p = ui.cursor_screen_pos(); - let spacing = 8.0; - let mut y = p[1] + 4.0; - for n in 0..2 { - let mut x = p[0] + 4.0; - let thickness = if n == 0 { 1.0 } else { 4.0 }; - draw_list - .add_circle( - [x + state.sz * 0.5, y + state.sz * 0.5], - state.sz * 0.5, - state.col, - ) - .num_segments(20) - .thickness(thickness) - .build(); - x += state.sz + spacing; - draw_list - .add_rect([x, y], [x + state.sz, y + state.sz], state.col) - .thickness(thickness) - .build(); - x += state.sz + spacing; - draw_list - .add_rect([x, y], [x + state.sz, y + state.sz], state.col) - .thickness(thickness) - .rounding(10.0) - .build(); - x += state.sz + spacing; - draw_list - .add_rect([x, y], [x + state.sz, y + state.sz], state.col) - .thickness(thickness) - .rounding(10.0) - .round_top_right(false) - .round_bot_left(false) - .build(); - x += state.sz + spacing; - draw_list - .add_triangle( - [x + state.sz * 0.5, y], - [x + state.sz, y + state.sz - 0.5], - [x, y + state.sz - 0.5], - state.col, - ) - .thickness(thickness) - .build(); - x += state.sz + spacing; - draw_list - .add_line([x, y], [x + state.sz, y], state.col) - .thickness(thickness) - .build(); - x += state.sz + spacing; - draw_list - .add_line([x, y], [x + state.sz, y + state.sz], state.col) - .thickness(thickness) - .build(); - x += state.sz + spacing; - draw_list - .add_line([x, y], [x, y + state.sz], state.col) - .thickness(thickness) - .build(); - x += spacing; - draw_list - .add_bezier_curve( - [x, y], - [x + state.sz * 1.3, y + state.sz * 0.3], - [x + state.sz - state.sz * 1.3, y + state.sz - state.sz * 0.3], - [x + state.sz, y + state.sz], - state.col, - ) - .thickness(thickness) - .build(); - y += state.sz + spacing; - } - let mut x = p[0] + 4.0; - draw_list - .add_circle( - [x + state.sz * 0.5, y + state.sz * 0.5], - state.sz * 0.5, - state.col, - ) - .num_segments(32) - .filled(true) - .build(); - x += state.sz + spacing; - draw_list - .add_rect([x, y], [x + state.sz, y + state.sz], state.col) - .filled(true) - .build(); - x += state.sz + spacing; - draw_list - .add_rect([x, y], [x + state.sz, y + state.sz], state.col) - .filled(true) - .rounding(10.0) - .build(); - x += state.sz + spacing; - draw_list - .add_rect([x, y], [x + state.sz, y + state.sz], state.col) - .filled(true) - .rounding(10.0) - .round_top_right(false) - .round_bot_left(false) - .build(); - x += state.sz + spacing; - draw_list - .add_triangle( - [x + state.sz * 0.5, y], - [x + state.sz, y + state.sz - 0.5], - [x, y + state.sz - 0.5], - state.col, - ) - .filled(true) - .build(); - x += state.sz + spacing; - const MULTICOLOR_RECT_CORNER_COLOR1: [f32; 3] = [0.0, 0.0, 0.0]; - const MULTICOLOR_RECT_CORNER_COLOR2: [f32; 3] = [1.0, 0.0, 0.0]; - const MULTICOLOR_RECT_CORNER_COLOR3: [f32; 3] = [1.0, 1.0, 0.0]; - const MULTICOLOR_RECT_CORNER_COLOR4: [f32; 3] = [0.0, 1.0, 0.0]; - draw_list.add_rect_filled_multicolor( - [x, y], - [x + state.sz, y + state.sz], - MULTICOLOR_RECT_CORNER_COLOR1, - MULTICOLOR_RECT_CORNER_COLOR2, - MULTICOLOR_RECT_CORNER_COLOR3, - MULTICOLOR_RECT_CORNER_COLOR4, - ); - ui.dummy([(state.sz + spacing) * 8.0, (state.sz + spacing) * 3.0]); - ui.separator(); - - ui.text("Canvas example"); - if ui.button("Clear") { - state.points.clear(); - } - if state.points.len() >= 2 { - ui.same_line(); - if ui.button("Undo") { - state.points.pop(); - state.points.pop(); - } - } - ui.text("Left-click and drag to add lines,\nRight-click to undo"); - // Here we are using InvisibleButton() as a convenience to - // 1) advance the cursor, and - // 2) allows us to use IsItemHovered() - // However you can draw directly and poll mouse/keyboard by - // yourself. You can manipulate the cursor using GetCursorPos() and - // SetCursorPos(). If you only use the ImDrawList API, you can - // notify the owner window of its extends by using - // SetCursorPos(max). - - // ImDrawList API uses screen coordinates! - let canvas_pos = ui.cursor_screen_pos(); - // Resize canvas to what's available - let mut canvas_size = ui.content_region_avail(); - if canvas_size[0] < 50.0 { - canvas_size[0] = 50.0; - } - if canvas_size[1] < 50.0 { - canvas_size[1] = 50.0; - } - const CANVAS_CORNER_COLOR1: [f32; 3] = [0.2, 0.2, 0.2]; - const CANVAS_CORNER_COLOR2: [f32; 3] = [0.2, 0.2, 0.24]; - const CANVAS_CORNER_COLOR3: [f32; 3] = [0.24, 0.24, 0.27]; - const CANVAS_CORNER_COLOR4: [f32; 3] = [0.2, 0.2, 0.24]; - draw_list.add_rect_filled_multicolor( - canvas_pos, - [ - canvas_pos[0] + canvas_size[0], - canvas_pos[1] + canvas_size[1], - ], - CANVAS_CORNER_COLOR1, - CANVAS_CORNER_COLOR2, - CANVAS_CORNER_COLOR3, - CANVAS_CORNER_COLOR4, - ); - const CANVAS_BORDER_COLOR: [f32; 3] = [1.0, 1.0, 1.0]; - draw_list - .add_rect( - canvas_pos, - [ - canvas_pos[0] + canvas_size[0], - canvas_pos[1] + canvas_size[1], - ], - CANVAS_BORDER_COLOR, - ) - .build(); - - let mut adding_preview = false; - ui.invisible_button("canvas", canvas_size); - let mouse_pos = ui.io().mouse_pos; - let mouse_pos_in_canvas = [mouse_pos[0] - canvas_pos[0], mouse_pos[1] - canvas_pos[1]]; - if state.adding_line { - adding_preview = true; - state.points.push(mouse_pos_in_canvas); - if !ui.is_mouse_down(MouseButton::Left) { - state.adding_line = false; - adding_preview = false; - } - } - if ui.is_item_hovered() { - if !state.adding_line && ui.is_mouse_clicked(MouseButton::Left) { - state.points.push(mouse_pos_in_canvas); - state.adding_line = true; - } - if ui.is_mouse_clicked(MouseButton::Right) && !state.points.is_empty() { - state.adding_line = false; - adding_preview = false; - state.points.pop(); - state.points.pop(); - } - } - draw_list.with_clip_rect_intersect( - canvas_pos, - [ - canvas_pos[0] + canvas_size[0], - canvas_pos[1] + canvas_size[1], - ], - || { - const LINE_COLOR: [f32; 3] = [1.0, 1.0, 0.0]; - for line in state.points.chunks(2) { - if line.len() < 2 { - break; - } - let (p1, p2) = (line[0], line[1]); - draw_list - .add_line( - [canvas_pos[0] + p1[0], canvas_pos[1] + p1[1]], - [canvas_pos[0] + p2[0], canvas_pos[1] + p2[1]], - LINE_COLOR, - ) - .thickness(2.0) - .build(); - } - }, - ); - if adding_preview { - state.points.pop(); - } - }); -} - -fn show_app_log(ui: &Ui, app_log: &mut Vec) { - ui.window("Example: Log") - .size([500.0, 400.0], Condition::FirstUseEver) - .build(|| { - if ui.small_button("[Debug] Add 5 entries") { - let categories = ["info", "warn", "error"]; - let words = [ - "Bumfuzzled", - "Cattywampus", - "Snickersnee", - "Abibliophobia", - "Absquatulate", - "Nincompoop", - "Pauciloquent", - ]; - for _ in 0..5 { - let category = categories[app_log.len() % categories.len()]; - let word = words[app_log.len() % words.len()]; - let frame = ui.frame_count(); - let time = ui.time(); - let text = format!( - "{:05} {} Hello, current time is {:.1}, here's a word: {}", - frame, category, time, word - ); - app_log.push(text); - } - } - if ui.button("Clear") { - app_log.clear(); - } - ui.same_line(); - if ui.button("Copy") { - ui.set_clipboard_text(ImString::from(app_log.join("\n"))); - } - ui.separator(); - ui.child_window("logwindow") - .flags(WindowFlags::HORIZONTAL_SCROLLBAR) - .build(|| { - if !app_log.is_empty() { - let mut clipper = ListClipper::new(app_log.len() as i32).begin(ui); - while clipper.step() { - for line in clipper.display_start()..clipper.display_end() { - ui.text(&app_log[line as usize]); - } - } - } - if ui.scroll_y() >= ui.scroll_max_y() { - ui.set_scroll_here_y(); - } - }); - }); -} diff --git a/imgui-examples/examples/text_callbacks.rs b/imgui-examples/examples/text_callbacks.rs deleted file mode 100644 index 5f2ce37..0000000 --- a/imgui-examples/examples/text_callbacks.rs +++ /dev/null @@ -1,136 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - let mut buffers = [String::default(), String::default(), String::default()]; - support::simple_init(file!(), move |_, ui| { - ui.window("Input text callbacks") - .size([500.0, 300.0], Condition::FirstUseEver) - .build(|| { - ui.text("You can make a variety of buffer callbacks on an Input Text"); - ui.text( - "or on an InputTextMultiline. In this example, we'll use \ - InputText primarily.", - ); - ui.text( - "The only difference is that InputTextMultiline doesn't get \ - the `History` callback,", - ); - ui.text("since, of course, you need the up/down keys to navigate."); - - ui.separator(); - - ui.text("No callbacks:"); - - ui.input_text("buf0", &mut buffers[0]).build(); - ui.input_text("buf1", &mut buffers[1]).build(); - ui.input_text("buf2", &mut buffers[2]).build(); - - ui.separator(); - - ui.text("Here's a callback which printlns when each is ran."); - - struct AllCallback; - impl InputTextCallbackHandler for AllCallback { - fn char_filter(&mut self, c: char) -> Option { - println!("Char filter fired! This means a char was inputted."); - Some(c) - } - fn on_completion(&mut self, _: TextCallbackData) { - println!("Completion request fired! This means the tab key was hit."); - } - - fn on_edit(&mut self, _: TextCallbackData) { - println!("Edit was fired! Any edit will cause this to fire.") - } - - fn on_history(&mut self, dir: HistoryDirection, _: TextCallbackData) { - println!("History was fired by pressing {:?}", dir); - } - - fn on_always(&mut self, _: TextCallbackData) { - // We don't actually print this out because it will flood your log a lot! - // println!("The always callback fired! It always fires."); - } - } - - ui.input_text("All Callbacks logging", buffers.get_mut(0).unwrap()) - .callback(InputTextCallback::all(), AllCallback) - .build(); - - ui.separator(); - - ui.text("You can also define a callback on structs with data."); - ui.text("Here we implement the callback handler on a wrapper around &mut String"); - ui.text("to duplicate edits to buf0 on buf1"); - - struct Wrapper<'a>(&'a mut String); - impl<'a> InputTextCallbackHandler for Wrapper<'a> { - fn on_always(&mut self, data: TextCallbackData) { - data.str().clone_into(self.0); - } - } - - let (buf0, brwchk_dance) = buffers.split_first_mut().unwrap(); - let buf1 = Wrapper(&mut brwchk_dance[0]); - - ui.input_text("Edits copied to buf1", buf0) - .callback(InputTextCallback::ALWAYS, buf1) - .build(); - - ui.separator(); - - ui.text("Finally, we'll do some whacky history to show inserting and removing"); - ui.text("characters from the buffer."); - ui.text( - "Here, pressing UP (while editing the below widget) will remove the\n\ - first and last character from buf2", - ); - ui.text("and pressing DOWN will prepend the first char from buf0 AND"); - ui.text("append the last char from buf1"); - - let (buf0, brwchk_dance) = buffers.split_first_mut().unwrap(); - let (buf1, buf2_dance) = brwchk_dance.split_first_mut().unwrap(); - let buf2 = &mut buf2_dance[0]; - - struct Wrapper2<'a>(&'a str, &'a str); - - impl<'a> InputTextCallbackHandler for Wrapper2<'a> { - fn on_history(&mut self, dir: HistoryDirection, mut data: TextCallbackData) { - match dir { - HistoryDirection::Up => { - // remove first char... - if !data.str().is_empty() { - data.remove_chars(0, 1); - - if let Some((idx, _)) = data.str().char_indices().next_back() { - data.remove_chars(idx, 1); - } - } - } - HistoryDirection::Down => { - // insert first char... - if let Some(first_char) = self.0.get(0..1) { - data.insert_chars(0, first_char); - } - - // insert last char - if let Some((idx, _)) = self.1.char_indices().next_back() { - data.push_str(&self.1[idx..]); - } - } - } - } - } - - ui.input_text("Wild buf2 editor", buf2) - .callback(InputTextCallback::HISTORY, Wrapper2(buf0, buf1)) - .build(); - - ui.text( - "For more examples on how to use callbacks non-chaotically, check the demo", - ); - }); - }); -} diff --git a/imgui-examples/examples/text_input.rs b/imgui-examples/examples/text_input.rs deleted file mode 100644 index da7e320..0000000 --- a/imgui-examples/examples/text_input.rs +++ /dev/null @@ -1,46 +0,0 @@ -use imgui::*; - -mod support; - -fn main() { - let mut stable_str = String::new(); - let mut callback_str = String::new(); - - support::simple_init(file!(), move |_, ui| { - if let Some(_window) = ui - .window("Input text callbacks") - .size([500.0, 300.0], Condition::FirstUseEver) - .begin() - { - if ui.input_text("input stable", &mut stable_str).build() { - dbg!(&stable_str); - } - - let mut per_frame_buf = String::new(); - ui.input_text("input per frame", &mut per_frame_buf).build(); - - if ui.is_item_deactivated_after_edit() { - dbg!(&per_frame_buf); - } - - struct CB; - impl imgui::InputTextCallbackHandler for CB { - fn on_history( - &mut self, - _dir: imgui::HistoryDirection, - _data: imgui::TextCallbackData, - ) { - } - } - let changed = ui - .input_text("input callback", &mut callback_str) - .callback(InputTextCallback::HISTORY, CB) - .enter_returns_true(true) - .build(); - - if changed { - println!("{:?}", callback_str); - } - } - }); -} diff --git a/imgui/Cargo.toml b/imgui/Cargo.toml index 8706474..57eccef 100644 --- a/imgui/Cargo.toml +++ b/imgui/Cargo.toml @@ -17,7 +17,7 @@ features = ["freetype", "docking", "tables-api"] [dependencies] bitflags = "1" -imgui-sys = { version = "0.12.0", path = "../imgui-sys" } +imgui-sys = { path = "../imgui-sys", version = "0.12" } mint = "0.5.6" parking_lot = "0.12" cfg-if = "1" @@ -31,4 +31,4 @@ docking = ["imgui-sys/docking"] tables-api = [] [dev-dependencies] -memoffset = "0.9" +memoffset = "0.9" \ No newline at end of file diff --git a/imgui/src/input_widget.rs b/imgui/src/input_widget.rs index faa739a..06109be 100644 --- a/imgui/src/input_widget.rs +++ b/imgui/src/input_widget.rs @@ -184,12 +184,12 @@ impl<'ui, 'p, L: AsRef> InputText<'ui, 'p, L> { /// by appending and then removing a null terminator (`\0`) from the String you pass in. /// This has several consequences: /// 1. The string's backing buffer may be resized and relocated even without edits as result - /// of this pushed char. + /// of this pushed char. /// 2. **The string will appear truncated if the string contains `\0` inside it.** This will not - /// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process - /// your string. + /// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process + /// your string. /// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point. - /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. + /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. pub fn new(ui: &'ui Ui, label: L, buf: &'p mut String) -> Self { InputText { label, @@ -280,12 +280,12 @@ where /// by appending and then removing a null terminator (`\0`) from the String you pass in. /// This has several consequences: /// 1. The string's backing buffer may be resized and relocated even without edits as result - /// of this pushed char. + /// of this pushed char. /// 2. **The string will appear truncated if the string contains `\0` inside it.** This will not - /// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process - /// your string. + /// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process + /// your string. /// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point. - /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. + /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. pub fn build(self) -> bool { // needs to be null-terminated! this is a hack! self.buf.push('\0'); @@ -367,12 +367,12 @@ impl<'ui, 'p, L: AsRef> InputTextMultiline<'ui, 'p, L, PassthroughCallback> /// by appending and then removing a null terminator (`\0`) from the String you pass in. /// This has several consequences: /// 1. The string's backing buffer may be resized and relocated even without edits as result - /// of this pushed char. + /// of this pushed char. /// 2. **The string will appear truncated if the string contains `\0` inside it.** This will not - /// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process - /// your string. + /// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process + /// your string. /// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point. - /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. + /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. pub fn new(ui: &'ui Ui, label: L, buf: &'p mut String, size: impl Into) -> Self { InputTextMultiline { label, @@ -441,12 +441,12 @@ impl<'ui, 'p, T: InputTextCallbackHandler, L: AsRef> InputTextMultiline<'ui /// by appending and then removing a null terminator (`\0`) from the String you pass in. /// This has several consequences: /// 1. The string's backing buffer may be resized and relocated even without edits as result - /// of this pushed char. + /// of this pushed char. /// 2. **The string will appear truncated if the string contains `\0` inside it.** This will not - /// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process - /// your string. + /// cause memory *unsafety*, but it will limit your usage. If that's the case, please pre-process + /// your string. /// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point. - /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. + /// We will handle this for you and edit the string "properly" too, but this might show up in callbacks. pub fn build(self) -> bool { // needs to be null-terminated! this is a hack! self.buf.push('\0'); diff --git a/imgui/src/stacks.rs b/imgui/src/stacks.rs index 4bebde1..e730cc5 100644 --- a/imgui/src/stacks.rs +++ b/imgui/src/stacks.rs @@ -187,7 +187,7 @@ impl Ui { /// - `> 0.0`: width is `item_width` pixels /// - `= 0.0`: default to ~2/3 of window width /// - `< 0.0`: `item_width` pixels relative to the right of window (-1.0 always aligns width to - /// the right side) + /// the right side) #[doc(alias = "PushItemWith")] pub fn push_item_width(&self, item_width: f32) -> ItemWidthStackToken<'_> { unsafe { sys::igPushItemWidth(item_width) }; @@ -198,7 +198,7 @@ impl Ui { /// - `> 0.0`: width is `item_width` pixels /// - `= 0.0`: default to ~2/3 of window width /// - `< 0.0`: `item_width` pixels relative to the right of window (-1.0 always aligns width to - /// the right side) + /// the right side) #[doc(alias = "SetNextItemWidth")] pub fn set_next_item_width(&self, item_width: f32) { unsafe { sys::igSetNextItemWidth(item_width) }; diff --git a/imgui/src/tables.rs b/imgui/src/tables.rs index 181ec35..2536c2a 100644 --- a/imgui/src/tables.rs +++ b/imgui/src/tables.rs @@ -356,13 +356,11 @@ impl Ui { inner_width: f32, ) -> Option> { self.begin_table_with_sizing(str_id, N, flags, outer_size, inner_width) - .map(|data| { + .inspect(|_data| { for value in column_data { self.table_setup_column_with(value); } self.table_headers_row(); - - data }) } diff --git a/imgui/src/tokens.rs b/imgui/src/tokens.rs index 83525d1..f4d9d4c 100644 --- a/imgui/src/tokens.rs +++ b/imgui/src/tokens.rs @@ -36,6 +36,7 @@ macro_rules! create_token { impl Drop for $token_name<'_> { fn drop(&mut self) { + #[allow(clippy::macro_metavars_in_unsafe)] unsafe { $on_drop } } } diff --git a/xtask/src/bindgen.rs b/xtask/src/bindgen.rs index 57e9af1..a2e853e 100644 --- a/xtask/src/bindgen.rs +++ b/xtask/src/bindgen.rs @@ -22,7 +22,7 @@ impl Bindgen { None => "".to_string(), Some(x) => format!("-{}", x), }; - let cimgui_output = root.join(&format!( + let cimgui_output = root.join(format!( "imgui-sys/third-party/imgui-{}{}", variant, additional )); @@ -41,7 +41,7 @@ impl Bindgen { generate_binding_file(&header, &output.join(&output_name), &types, &funcs, None)?; generate_binding_file( &header, - &output.join(&format!("wasm_{}", &output_name)), + &output.join(format!("wasm_{}", &output_name)), &types, &funcs, Some(&wasm_name),