OpenGL in DisplayConduit

Hey!

Is your project’s source code somewhere available? It would be great to see some Imgui + Rhino example as in the Rhino world Imgui is not so popular, yet it looks brilliant as a UI system in many cases.

Hello @w.radaczynski

Yes, ImGui is really awesome, dynamic and easy to use.
A small example of control customization (the ToogleButton), it takes a few lines.

ImGui.NET DrawToggleButton
ImVec4 _fgColor   = new (255, 255, 255, 255);   // Foreground color
ImVec4 _bgDefault = new (218, 218, 218, 255);   // Background colors
ImVec4 _bgEnabled = new (145, 211, 68, 255);    // 
ImVec4 _bgHovered = new (20, 20, 20, 0);        // (an offset)

// https://github.com/ocornut/imgui/issues/1537#issuecomment-355562097
void DrawToggleButton (string str_id, ref bool v)
{
    var p = IM.GetCursorScreenPos ();           // Position on the screen where to draw the control.
    var draw_list = IM.GetWindowDrawList ();    // Data to draw with OpenGL

    float height = IM.GetFrameHeight ();        // Control height. (Font size + padding*)
    float width = height * 1.55f;
    float radius = height * 0.50f;

    if (IM.InvisibleButton (str_id, new ImVec2 (width, height)))    // Adding a clickable area
        v = !v;

    uint col_bg = IM.IsItemHovered ()                               // Define background color
        ? (v ? ToU32 (_bgEnabled + _bgHovered) : ToU32 (_bgDefault - _bgHovered))
        : (v ? ToU32 (_bgEnabled) : ToU32 (_bgDefault));

    // Adding the control to the drawing list
    draw_list.AddRectFilled (p, new ImVec2 (p.X + width, p.Y + height), col_bg, height * 0.5f);
    draw_list.AddCircleFilled (new ImVec2 (v ? p.X + width - radius : p.X + radius, p.Y + radius), radius - 1.5f, ToU32 (_fgColor));

    // Adding the label
    IM.SameLine ();
    IM.Text (str_id.Split ('#')[0]);

    // Same as Imgui.ColorConvertFloat4ToU32
    static uint ToU32 (ImVec4 v) => (uint)v.W << 24 | (uint)v.Z << 16 | (uint)v.Y << 8 | (uint)v.X << 0;
}

In short, it’s a 2d library with user input functions (mouse, keyboard).
This approach is nearly identical to the Blender interface and has similarities to the Grasshopper canvas.
The big deal is its integration into the Rhino pipeline (that’s the reason for this thread and the 4 years since my first post)

Well currently, no the source code is not available but maybe. In fact, I would make the sources available if I find people who want to contribute to the development.

Recently I rewrote this library in C++ with C# bindings. Currently there is not much that works, I have to reimplement the controls in C. But I’m not a developer, I’m not an expert in C++/OpenGL and my time available for this project is limited.

It may take a while before I can share anything.
I use this post to call anyone who wants to contribute (C++<->C#).

jmv

3 Likes

I didn’t realize you were drawing the boxes in the video. I thought that was some sort of selected object drawing. If you draw the boxes before the UI, then I would expect things to look correct. Using DrawOverlay instead of DrawForeground may improve performance with heavy models as the entire scene wouldn’t need to be redrawn

1 Like

Hey @kitjmv, how complex an undertaking is writing these UI elements? What would be useful to know before trying?

1 Like

Hello,

Hard to say, it depends on your level of programming, you need to consider 3 parts:

  • Understand and be able to use ImGui lib
  • Understand and be able to use OpenGL in Rhino
  • And be able to hack Rhino user input events (mouse and keyboards)

If, like me, you are starting from scratch, it is difficult. But if you are an expert in OpenGL (C++) and system events (C++ Windows/Mac), I think you can do a proof of concept in a month.

ImGui lib looks difficult on first try, but after taking the time to read the entire source file, it’s not a very difficult library.

Same for OpenGL. knowing the procedures imposed by the library is enough to make it work. Today I understand opengl better and Rhino integration is simple. In fact there is nothing to do (OpenGL in DisplayConduit - #13 by jeff), just restore the OpenGL settings changes (OpenGL in DisplayConduit - #16 by jeff).

Rhino’s input events are probably the hardest part.

Due to the lack of Rhino API, we cannot catch some user input events needed for ImGui.

For example, there is no way in the Rhino API to catch the mouse wheel and not zoom the Rhino viewport .
Another problem concerns keyboard events. All keystrokes are captured by the Rhino command line, so when you write in an ImGui text field, you are also writing in the Rhino command line.

The only way to hack Rhino’s mouse/keyboard events is to use a low-level native platform listener.
“low-level” means you should catch all system events, regardless of thread or application (all system-wide events).
I don’t like this way, but I don’t know of any other way to intercept user inputs before Rhino’s viewport.

jmv

1 Like

Thanks for such a well thought out answer @kitjmv, it seems I must not underestimate Graphics libraries :slight_smile: