Rust-Imgui rs: imgui-rs — Rust bindings for ImGui

imgui-rs: Rust bindings for Dear ImGui

Still fairly experimental!

Minimum Rust version: 1.40

Wrapped Dear ImGui version: 1.76

Build Status Latest release on crates.io Documentation on docs.rs

Hello world

Window::new(im_str!("Hello world"))
    .size([300.0, 100.0], Condition::FirstUseEver)
    .build(&ui, || {
        ui.text(im_str!("Hello world!"));
        ui.text(im_str!("こんにちは世界!"));
        ui.text(im_str!("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]
        ));
    });

Main library crates

  • imgui: High-level safe API
  • imgui-glium-renderer: Renderer implementation that uses the glium crate
  • imgui-gfx-renderer: Renderer implementation that uses the gfx crate (not the new gfx-hal crate)
  • imgui-winit-support: Backend platform implementation that uses the winit crate (0.22 by default, but 0.19-0.21 are supported via feature flags)
  • imgui-sys: Low-level unsafe API (automatically generated)

Features

  • Bindings for Dear ImGui that can be used with safe Rust. Note: API coverage is not 100%, but will keep improving over time.
  • Builder structs for use cases where the original C++ library uses optional function parameters
  • &ImStr / ImString types and im_str! macro for defining and passing null-terminated UTF-8 to Dear ImGui, which doesn't accept Rust &str / String values. See issue #7 for more information and justification for this design.
  • Easy integration with Glium / pre-ll gfx (renderer)
  • Easy integration with winit (backend platform)

Choosing a backend platform and a renderer

Almost every application that uses imgui-rs needs two additional components in addition to the main imgui crate: a backend platform, and a renderer.

The backend platform is responsible for integrating imgui-rs with the operating system and its window management. Its responsibilities include the following:

  • Handling input events (e.g. keyboard, mouse) and updating imgui-rs state accordingly
  • Passing information about the OS window (e.g. size, DPI factor) to imgui-rs
  • Updating the OS-side mouse cursor when imgui-rs requests it

The renderer is responsible for taking generic, renderer-agnostic draw lists generated by imgui-rs, and rendering them using some graphics API. Its responsibilities include the following:

  • Rendering using vertex/index buffers and command lists
  • Handling of DPI factors and scissor rects
  • Texture management

The most tested platform/renderer combination is imgui-glium-renderer + glium + imgui-winit-support + winit, but this is not the only possible combination. There's also imgui-gfx-renderer, and you can find additional 3rd party crates that provide a wider support for more libraries (e.g. raw OpenGL, SDL2). You can also write your own support code if you have a more advanced use case, because imgui-rs is not tied to any specific graphics / OS API.

Compiling and running the demos

git clone https://github.com/Gekkio/imgui-rs
cd imgui-rs
git submodule update --init --recursive

Main examples are located in the imgui-examples directory.

# At the reposity root
cd imgui-examples
cargo test

cargo run --example hello_world
cargo run --example test_window
cargo run --example test_window_impl

Examples for the gfx backend are under the imgui-gfx-examples directory.

cd imgui-gfx-examples
cargo test

cargo run --example hello_world
cargo run --example test_window

Note to Windows users: You will need to use the MSVC ABI version of the Rust compiler along with its associated dependencies to build this libary and run the examples.

How to contribute

  1. Change or add something

  2. Make sure you're using the latest stable Rust

  3. Run rustfmt to guarantee code style conformance

    rustup component add rustfmt
    cargo fmt
  4. Open a pull request in Github

License

Licensed under either of

at your option.

Uses Dear ImGui and cimgui.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments

  • Make cmd_lists_count public in DrawData struct
    Make cmd_lists_count public in DrawData struct

    May 23, 2020

    Also updated comments with latest from imgui.

    Relates to https://github.com/Gekkio/imgui-rs/issues/325

    Reply
  • Manually managing tooltips
    Manually managing tooltips

    May 25, 2020

    Add ability to create tooltips without passing a lambda. Essentially, it's a copy-paste from Ui::begin_group() and uses the same Token-based implementation. As with other methods like this, it's very useful when dealing with mutable references both before and inside lambda.

    Reply
  • Modifier keys always false on winit + mac
    Modifier keys always false on winit + mac

    Jun 5, 2020

    On master, on Mac Catalina.

    Reproduce: in imgui-gfx-examples/examples/hello_world.rs, add:

    ui.text(format!("key_shift: {}", ui.io().key_shift));
    ui.text(format!("key_ctrl: {}", ui.io().key_ctrl));
    ui.text(format!("key_alt: {}", ui.io().key_alt));
    ui.text(format!("key_super: {}", ui.io().key_super));
    

    Run cargo run --example hello_world and press modifier keys. They all remain false.

    A short investigation of imgui-winit-support/src/lib.rs shows that I do get WindowEvent::KeyboardInput in

        #[cfg(feature = "winit-19")]
        fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &WindowEvent) {
            ...
        }
    

    Maybe the modifier keys should be updated there

    Reply
  • Discussion: the road to 0.5
    Discussion: the road to 0.5

    Jun 5, 2020

    Previous release discussions:

    • 0.4: https://github.com/Gekkio/imgui-rs/issues/301
    • 0.3: https://github.com/Gekkio/imgui-rs/issues/267
    • 0.2: https://github.com/Gekkio/imgui-rs/issues/238
    • 0.1: https://github.com/Gekkio/imgui-rs/issues/167
    Reply
  • Added a feature to support the imgui features to use u32 draw indices
    Added a feature to support the imgui features to use u32 draw indices

    Jun 11, 2020

                                                                                                                                                                                                           
    Reply
  • Cannot abstract out window contents, Ui is borrowed by build()
    Cannot abstract out window contents, Ui is borrowed by build()

    Jun 14, 2020

    So here's a conundrum. I am currently working on an editor for my game engine. At this point I am trying to create document windows for different types of assets. I have a Document trait with a function taking an &mut Ui, so that it can specify what the document window contents should be. Unfortunately, this does not play nice with Rust's borrowing rules:

    imgui::Window::new(&im_str!("{}", document.window_name())).focused(raise).opened(&mut window_open).position([320.0, 48.0], imgui::Condition::Appearing)
        .size([640.0, 640.0], imgui::Condition::Appearing).build(ui, ||
    {
        document.do_ui(editor, ui);
    });
    
    error[E0500]: closure requires unique access to `ui` but it is already borrowed
        |
    420 |     .size([640.0, 640.0], imgui::Condition::Appearing).build(ui, ||
        |                                                        ----- --  ^^ closure construction occurs here
        |                                                        |     |
        |                                                        |     borrow occurs here
        |                                                        first borrow later used by call
    421 | {
    422 |     document.do_ui(editor, ui);
        |                            -- second borrow occurs due to use of `ui` in closure
    

    Is there any way to solve this?

    Reply
  • Expose more functionality from imgui.
    Expose more functionality from imgui.

    Jul 1, 2017

    Implement new_line(), calc_text_size(), and with_style_var_pushed_*() methods I needed while making a demo.

    I'm pretty new to Rust, but ran into this issue and thought I could maybe solve it while I was learning the library. https://github.com/Gekkio/imgui-rs/issues/39

    I'm curious on your thoughts on these additions. Please LMK if you would prefer a different direction, I'm pretty new to both Rust and this library so please let me know if you have any suggestions!

    I'm hoping to contribute to this library moving forward, as I work on my game's UI.

    Reply
  • Support for Text Input
    Support for Text Input

    Oct 8, 2015

    I've got rough support for text input working but at the moment we do a kind of nasty cast of the char to a u16. We really should be using encode_utf8 or whatever stabilizes in its place to send ImGUI an array of utf8 characters.

    Along with this I've been working on keyboard support in the examples but seem to have some issues with glutin not giving me virtual keycodes for keys like ctrl and shift and such. I'm also looking for a way to get the scancode for a virtual key so we can tell ImGUI where the arrows, A, Z, tab, ctrl and so on are located. If you've had good luck with SDL2 I may just use this in my project but it's still needed for the demo to work cleanly. I'll have to ask in the IRC about this.

    Let me know what you think!

    Reply
  • Add compiling notice for Windows users in README
    Add compiling notice for Windows users in README

    Jul 17, 2016

    The library will compile with the GNU version of the Rust if the underlying required Windows dependencies can be found during compilation but runtime errors will occur when running the samples due to the incompatible ABI. I built the library and ran the examples successfully on two different machine running different versions of Windows using the Rust MSVC compiler with the latest Visual Studio 2015 C++ tools installed.

    Reply
  • Discussion: the road to 0.1
    Discussion: the road to 0.1

    Oct 18, 2018

    I've been thinking about doing some big refactorings in the project and doing a big push towards a 0.1 release. There's a couple of main topics I'd like to mention here:

    Automatic generation of bindings

    In imgui-rs, we don't currently use bindgen and all the imgui-sys bindings are maintained by hand, which sometimes leads to human errors (fixed one mistake today I made in the latest cimgui upgrade). bindgen has been suggested in the past (most recently in #139) but there has been some cons in the approach, which is why I haven't been very excited about the idea. However, cimgui recently switched to automatic generation, which greatly changes the dynamics around the C bindings. I've got a WIP branch testing an approach that is slightly different to the previously suggested approach:

    • instead of binding directly to Dear ImGui which generates non-portable C++ bindings, bind to cimgui which gives us portable C bindings. There's some non-portable preprocessor ifdefs, but those don't seem to end up affecting the generated Rust bindings
    • instead of generating bindings at build-time which adds LLVM as a hard dependency, just regenerate bindings manually after every cimgui upgrade. Since the generated bindings are portable, there's no need to generate them on the fly

    Let's take a look at the cons I listed in #139:

    • breaks pretty much all existing code (because many imgui-sys types are used in safe code too). This still applies, because we're replacing the entire imgui-sys API with an automatically generated one
    • user code becomes a mix of idiomatic and non-idiomatic code (because imgui-sys is used in safe code too). This can still apply, but my next suggestion about the roles of -sys and the main crate should help
    • ~~using bindgen with build.rs makes compiling much more complicated (e.g. LLVM is required on Windows. Do the bindings work with both msvc and gnu ABIs?)~~ Things should keep working on Windows just like they do now
    • ~~LLVM 3.9 requirement means imgui-rs won't work out-of-the-box on Debian stable or old Ubuntu 16.04 LTS~~ LLVM won't be a requirement to use imgui-rs
    • ~~a lot of magic in build.rs~~. Some "magic configuration" is still needed, but we can depend on cimgui to handle most of these things
    • ~~bindgen has some limitations with C++. Are we sure the bindings work on all platforms and continue to work without causing a maintenance nightmare?~~ C++ limitations don't apply. We'll depend on cimgui to provide correct C bindings and there's a possibility of errors there, but cimgui is used by other bindings too so there's less risk than if we maintained complicated configuration ourselves

    As a summary, it looks like the main downsides are

    1. Breakage of existing code. This is inevitable with 0.1 anyway
    2. Complications caused by how imgui-sys and imgui are partitioned. This leads to my next topic ->

    Roles of imgui-sys and imgui

    Right now, the main imgui crate uses many types from imgui-sys in its public API, and there's quite a lot of useful stuff, including documentation comments, in imgui-sys. This approach won't work with auto-generated bindings very well, because some things (like documentation comments) simply can't be added to the auto-generated stuff directly. This is why I'm experimenting with the idea of making imgui-sys to contain just the auto-generated bindings and nothing else. This will make the API of imgui-sys very annoying to use. However, we can then focus on providing a good API and documentation in the main crate. Some very basic "helpers" like extra ImVec2/ImVec4 conversions will still stay in imgui-sys, but all other manual code will be removed.

    Tightening safety holes

    I intend to do a big "sweep" over the entire API and fix all the safety holes I find, but this will cause API changes. There's already some known holes and I'm sure there's even more. I can immediately think of two:

    • UB because you can create multiple ImGuiContexts and break some invariants
    • UB because you can have a normal reference to ImGuiStyle but accidentally mutate it and break basic Rust guarantees about references

    Adding rustdoc documentation

    I intend to add Rustdoc documentation comments to most things in the imgui crate API. imgui-sys won't have any docs since the main point is to just export the auto-generated bindings.

    Reply
  • Wraps the dear ImGui custom drawing API
    Wraps the dear ImGui custom drawing API

    Mar 29, 2018

    This is an attempt at wrapping ImGui's custom drawing API.

    The custom rendering example provided with ImGui has been completely implemented. The result is as below:

    image

    Each patch should be self-explanatory and can be reviewed separately.

    This collection of patches can be split into 4 sections.

    • Implementation of window_draw_list.rs, the API itself
    • Add a few helper methods in Ui. These functions will be used for the examples.
    • Add show_example_app_custom_rendering in test_window_impl
    • Add another example test_drawing_channels_split, showing how channels_split can be used. => The example can be removed from this PR if you do not like it.

    This is an improvement over #102. With support for safe use of channels_split and generics to allow a more convenient use of the API.

    Reply
  • Update cimgui to 1.53.1
    Update cimgui to 1.53.1

    Apr 29, 2018

    Update cimgui, fixing #97 and #88.

    As a side note, the previous version has some compiler warning showing up during build:

    warning: third-party/cimgui/imgui/imgui.cpp: In function ‘void ImGui::RenderTriangle(ImVec2, ImGuiDir, float)’:
    warning: third-party/cimgui/imgui/imgui.cpp:3136:11: warning: this statement may fall through [-Wimplicit-fallthrough=]
    warning:          r = -r; // ...fall through, no break!
    warning:          ~~^~~~
    

    The new version has no warning.

    Reply