-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A panning / zooming container #1811
Comments
I would like to use egui_node_graph library in my project. The graph can be very big and for viewing and navigating zoom would be of great help to users. Without seeing the whole graph it is much harder to track all links/dependencies. |
This can be done using a ScrollArea. See this code as an example. |
@Barugon Not sure I follow. I understand ScrollArea lets you do panning, but does it allow zooming? What I mean is zooming in a way that all widgets and text would be scaled uniformly and without glitches, and regardless of whether they obey properties like |
Yeah, that might be pretty tricky. Maybe you could use |
Changing pixels per point would scale all the UI uniformly. You can think of this feature as a way to change pixels_per_point only for elements drawn inside a container. As far as I know, there is no way to achieve this in egui as it is today, because pixels_per_point is a global property and the layout engine doesn't have a notion of varying pixels_per_point. |
Yeah, I tried it and it won't work. egui needs some way to change an inner ui scale. |
FYI: Another option that seems to be working for me without altering the pixel_per_point is
It seems to be working quite well. The only issue I found is with some Resize widgets as they seem to preserve some maximum size after the zoom in/out and it creates some glitches. I guess this is the reason I could not use a window and had to fall back to Area as the main container for the graph nodes. |
FYI: https://github.com/gzp-crey/shine |
Another potential API for this would be to add a One limitation of |
The egui/crates/epaint/src/mesh.rs Lines 271 to 286 in 9c4f55b
Calling these methods after tessellating the shapes (i.e., at the end of this method) allows us to do some interesting things. Screencast.from.2023-09-17.21-55-10.webmBut to use that for a pan/zoom container, the code would have to be refactored to identify which mesh/shape is in which layer, to apply the appropriate transforms only to that layer (or each shape would have to have a copy of the transform). And the pointer coordinates within the UI corresponding to the transformed layer would have to be remapped with the inverse transform, so any widget within the layer would catch the events correctly. So I guess this method would have to update the transform matrix instead of applying the translation directly to the shapes within, so the same transform could be used to remap the pointer and then to translate/rotate/scale the meshes. Also, the |
@YgorSouza That takes care of display, but you also need to consider about event handling. In egui, widgets do event handling at draw time, so even if you could scale / translate the end result, you wouldn't be able to click any buttons in the scaled version. |
Hey @setzer22 , I'm interested in this issue, but I'm trying to follow the development. It looks like some things changed in egui 0.19, per this PR for blackjack, but I'm not sure what you were able to change (the PR is pretty big and not obvious to me). What is still missing in egui? Thank you! |
Hi @Engid 👋
I've been a bit out of the loop as of late, but as far as I understand, there has been no movement on the egui side. There's still no supported way to zoom or pan a UI container. The thing I have for blackjack is still the hack you can see described at the top of this post. The PR you link to helped clear some of the nasty parts in it, but the core of the implementation (two egui contexts, spoof winit events...) remains just as I described above. I am currently working on migrating the blackjack UI to a lower level architecture based on top of |
I think the linked PR should close this issue. As in the added pan+zoom demo, we will be able to translate and scale individual layers. This does mean each and every area/window will need to have the transformation applied to it (since the granularity is by |
⚠️ Removes `Context::translate_layer`, replacing it with a sticky `set_transform_layer` Adds the capability to scale layers. Allows interaction with scaled and transformed widgets inside transformed layers. I've also added a demo of how to have zooming and panning in a window (see the video below). This probably closes #1811. Having a panning and zooming container would just be creating a new `Area` with a new id, and applying zooming and panning with `ctx.transform_layer`. I've run the github workflow scripts in my repository, so hopefully the formatting and `cargo cranky` is satisfied. I'm not sure if all call sites where transforms would be relevant have been handled. This might also be missing are transforming clipping rects, but I'm not sure where / how to accomplish that. In the demo, the clipping rect is transformed to match, which seems to work. https://github.com/emilk/egui/assets/70821802/77e7e743-cdfe-402f-86e3-7744b3ee7b0f --------- Co-authored-by: tweoss <fchua@puffer5.stanford.edu> Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
⚠️ Removes `Context::translate_layer`, replacing it with a sticky `set_transform_layer` Adds the capability to scale layers. Allows interaction with scaled and transformed widgets inside transformed layers. I've also added a demo of how to have zooming and panning in a window (see the video below). This probably closes emilk#1811. Having a panning and zooming container would just be creating a new `Area` with a new id, and applying zooming and panning with `ctx.transform_layer`. I've run the github workflow scripts in my repository, so hopefully the formatting and `cargo cranky` is satisfied. I'm not sure if all call sites where transforms would be relevant have been handled. This might also be missing are transforming clipping rects, but I'm not sure where / how to accomplish that. In the demo, the clipping rect is transformed to match, which seems to work. https://github.com/emilk/egui/assets/70821802/77e7e743-cdfe-402f-86e3-7744b3ee7b0f --------- Co-authored-by: tweoss <fchua@puffer5.stanford.edu> Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
Is your feature request related to a problem? Please describe.
I work on the egui_node_graph library, which can be used to create node-graph based applications in egui. One particular feature of these kind of applications is being able to zoom and pan the graph view, as showcased in the gif below. To this date, I don't think that's possible to implement in egui in a portable way, but I managed to make it work for a specific integration (winit + wgpu) and a bunch of hacks.
I believe this can also be an interesting feature in other kinds of visualization-heavy applications: Right now there are things like the Plot view, which have this behavior available, but being able to use the full power of egui in a Zoomable / Pannable container feels like it would be the cleanest solution in many situations.
Describe the solution you'd like
It would be great if egui could offer a portable solution to create some sort of container in which you can apply pan and zoom. Tentatively, the API could look something like this?:
Describe alternatives you've considered
The current alternative, which is working for me but is highly non-portable and requires a bunch of patches on top of
egui
. The core idea is that I build two egui contexts, the one with the graph is rendered into a texture, and then that texture is drawn in the "parent" context as an egui::Image. This requires lots of messing around with thepixels_per_point
, the offsets of the nodes and the quads that are being sent to wgpu (in the integration) in a very precise way to prevent visual glitches. I also interceptwinit
events that go into the child instance to offset mouse positions and such: Not fun at all, as one might imagine 😅 Nothing would make me happier than being able to throw away all this code.I'm not sure I know enough about egui internals to see how a good implementation for this might look, but I assume it's possible, since egui is doing the rasterization: It would need to make sure it scales and offsets any meshes inside the Pan/Zoom area. It should also make sure a high-resolution texture with the fonts is available, since scaling up the fonts might look blurry otherwise.
Additional context

The text was updated successfully, but these errors were encountered: