egui_graphs icon indicating copy to clipboard operation
egui_graphs copied to clipboard

Render order of nodes and edges causes a 1 frame graphical glitch.

Open XertroV opened this issue 1 year ago • 1 comments

https://github.com/blitzarx1/egui_graphs/blob/416a211ffdfd46aabb3d8bb73a69bbce2b004985/src/draw/drawer.rs#L60-L63

Here, edges are drawn first, then nodes. In fill_layers_nodes, the nodes position is updated based on the node props. So, if you add a node to the graph, then for the first frame the edge that gets drawn thinks the node is at 0,0 because the position has not yet been updated. (I think)

This might be related to the fact I'm adding the node with a custom shape and a position, or extending the graph live.

Swapping the order of these two calls fixed the issue for me, except that edges are now drawn over nodes.

alternative soln 1

I patched the code like this:

    pub fn draw(mut self) {
        self.update_nodes();
        self.draw_edges();
        self.fill_layers_nodes();
    }

    fn update_nodes(&mut self) {
        self.g
            .g
            .node_indices()
            .collect::<Vec<_>>()
            .into_iter()
            .for_each(|idx| {
                let n = self.g.node_mut(idx).unwrap();
                // note: added this simple function (body is just: `self.display.update(&self.props)`)
                n.update_display_from_props();
            });
    }

    fn fill_layers_nodes(&mut self) {
        self.g
            .g
            .node_indices()
            .collect::<Vec<_>>()
            .into_iter()
            .for_each(|idx| {
                let n = self.g.node_mut(idx).unwrap();
                // note: no update here anymore
                let display = n.display_mut();
                let shapes = display.shapes(self.ctx);

                if n.selected() || n.dragged() {
                    shapes.into_iter().for_each(|s| {
                        self.layer_top.add(s);
                    });
                } else {
                    shapes.into_iter().for_each(|s| {
                        self.layer_bot.add(s);
                    });
                }
            });
    }
    ```

### alternative 2

The user can fix this themselves, technically. (the node.update_display_from_props() function helps)

Basically I added 1 line to my code (the call to update from props) and restored the original `fn draw` and `fn fill_layers_nodes`

My code is now like this (in the part that adds nodes)

```rust
    let node_ix = add_node_custom(g, tip, |ix, hp| {
        let mut n = Node::new(hp.clone());
        n.set_label(format!("↑{}", hp.0.height));
        n.bind(
            ix,
            Pos2::new(
                NODE_SPACING * hp.0.category as f32,
                hp.0.height as f32 * -NODE_SPACING,
            ),
        );
        // added this line
        n.update_display_from_props();
        n
    });

XertroV avatar Feb 12 '24 01:02 XertroV

This needs further investigation. Will return to it soon

blitzarx1 avatar Aug 08 '24 12:08 blitzarx1