Egui vs makepad for OpenGL / WebGL

How does egui compare to GitHub - makepad/makepad: Makepad is a creative software development platform for Rust that compiles to wasm/webGL, osx/metal, windows/dx11 linux/opengl for OpenGL / WebGL UI ?

Superficially, it appears egui is much more lightweight than makepad, but I am wondering if there are some difficult-to-implement features of makepad that egui is missing.

In particular, is there anything resembling an IDE built in egui ?

1 Like

I don't think makepad has had a usable release yet, so egui is probably your best bet. Egui also has a lot of nice widgets that are ready to use.

Be aware that egui is an immediate mode gui, so its performance will be lower if you have lots of widgets/data points, etc. compared to retained mode gui frameworks. However, I haven't found something comparable to egui (with similar functionality, and all those nice widgets) that's free and uses retained mode gui (but I also haven't searched for very long).

There's also areweguiyet.com (but I'm not sure how up to date it is) if you're looking for other alternatives.

1 Like

That part about "retained", I wonder why nobody has a work-around. It does not look like it would be impossible. If you have a complex widget, it seems like the triangle data could just be saved in a buffer and only update it if there is a change.

I guess it is easy to say , someone should do it..

There's an open issue about it.

There is active research in the area of UI architecture for Rust. Raph Levien has a lot of interesting ideas, e.g: Xilem: an architecture for UI in Rust | Raph Levien’s blog

1 Like

Imagine we have:

InputEvent = Mouse | Keyboard | ...

fn draw(tri: &Vec<Triangle>) { ..... }

fn get_events() -> Vec<InputEvent> { ... }

app_state: AppState;

so then immediate mode looks like:

loop {
  events = get_events();
  app_state.mut_update(events);
  draw(app_state.gen_triangles());
}

while retained mode looks like:

let mut old_triangles: Vec<Triangle> = ... ;
loop {
  events = get_events();
  app_state.mut_update(events, old_triangles);
  draw(old_triangles);
}

i.e. 'bashing the old triangle list in place' vs 'generating a new one every frame' ?

Generally, instead it would be app_state.draw(), and that would be a tree of (just updated) widgets that store whatever drawing state (including triangles) they need and update it.

There's generally also a separate layout pass, often actually two passes for each component to measure and then position themselves first.

It's quite different, and often gets really messy, as the traditional approach mixes up drawing and logical code.