-
-
Notifications
You must be signed in to change notification settings - Fork 988
Add lasso selection to node graph #3333
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
base: master
Are you sure you want to change the base?
Add lasso selection to node graph #3333
Conversation
4059fde to
9e255fa
Compare
|
I should say while this is on my mind right now, performance should probably be looked at for this PR. We convert the entire vec of polygon points from one unit to another once every frame. |
0HyperCube
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your work on this. It seems to work nicely.
It is good to hear you thinking about the performance. However current architectural decisions unfortunately means an excessive number of allocations are necessary.
| /// plus a flag indicating if it has been dragged since the mousedown began. | ||
| lasso_selection_curr: Option<(Vec<DVec2>, bool)>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: It is probably clearer to make a struct { lasoo_points: Vec<DVec2>, has_dragged: bool } rather than relying on the doc comment to name the fields. However I suppose the current implementation is consistent with the box selection.
I wonder if it is even necessary to store the has_dragged bool. Can't you just check if the number of points is ≥ 2?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re: paragraph 2. Good point, pretty sure that's all the functionality that the dragged bool is used for in the box selection logic anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. Perhaps the has_dragged field helps make it explicit that we do something related to whether we have moved from the initial mousedown or not. But I agree with removing it.
Also, I took a look, and the only reason box selection can't do without the field either is because we want to update_node_graph_hints only after moving from the initial mousedown. That is, if the initial mousedown was to update the hints, we could remove the field. But for the analogous lasso logic, we just check if the length is at least two, again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implemented in 4f86201 below
| let lasso_selection_viewport: Vec<DVec2> = lasso_selection_curr | ||
| .iter() | ||
| .map(|selection_point| network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.transform_point2(*selection_point)) | ||
| .collect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no need to call .collect() since you use into_iter() later. You might have to move the frontend message to here though if the borrow checker is unhappy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The borrow checker indeed was. And yes, moving the frontend message there fixes it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implemented in 49efe27 below
| // WARNING WARNING WARNING: this commented-out code is copy pasted from UpdateBoxSelection above and has not been edited for lasso | ||
| // The mouse button was released but we missed the pointer up event | ||
| // if ((e.buttons & 1) === 0) { | ||
| // completeBoxSelection(); | ||
| // boxSelection = undefined; | ||
| // } else if ((e.buttons & 2) !== 0) { | ||
| // editor.handle.selectNodes(new BigUint64Array(previousSelection)); | ||
| // boxSelection = undefined; | ||
| // } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this relating to? It looks like javascript.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh neat, that is javascript for some reason. Yeah, the identical comment appears in UpdateBoxSelection, and got copied over when I copy-pasted the entire UpdateBoxSelection block. Didn't know if it was important so I left it.
To answer the question more explicitly, don't really know what this relates to, but your guess would be better than mine anyhow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The box selection seems to be working fine for many months, so it is probably safe to delete this comment (in both places).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implemented in 4f86201 below
| let node_graph_point = network_metadata | ||
| .persistent_metadata | ||
| .navigation_metadata | ||
| .node_graph_to_viewport |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Probably less verbose to let node_graph_to_viewport = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implemented in 0aa3860 below
| if nodes != previous_selection { | ||
| responses.add(NodeGraphMessage::SelectedNodesSet { | ||
| nodes: nodes.into_iter().collect::<Vec<_>>(), | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is probably easiest to just always send this message (rather than allocating the previous_selection HashMap each frame).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't intuit which is better, but I'll take your word for it. When I or whoever makes the change, I assume they should also make the identical analogous change to the box selection code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it doesn't matter very much either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving it for now, then.
| fn points_to_polygon(points: &[DVec2]) -> Vec<PathSeg> { | ||
| points | ||
| .windows(2) | ||
| .map(|w| PathSeg::Line(Line::new(dvec2_to_point(w[0]), dvec2_to_point(w[1])))) | ||
| .chain(std::iter::once(PathSeg::Line(Line::new( | ||
| dvec2_to_point(*points.last().unwrap()), | ||
| dvec2_to_point(*points.first().unwrap()), | ||
| )))) | ||
| .collect() | ||
| } | ||
| points_to_polygon(lasso_selection_curr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than allocating, consider a simplye point in polygon algorithm https://wrfranklin.org/Research/Short_Notes/pnpoly.html.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I feel the disappeal of needing to allocate, but I'm not sure how point-in-polygon helps. I stole click_targets.node_click_target.intersect_path from... uh, probably the box selection code, and I didn't look further because I knew it worked. I'd need to think about it lots and dig deeper into the code, but first impression: aren't nodes not points? We rather need nodes (rounded rectangles) in polygon?
That is, without some digging, I currently don't know how to get the bounding boxes of all the nodes.
editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs
Show resolved
Hide resolved
0203b77 to
7e4eb0f
Compare
7e4eb0f to
03aa7f9
Compare
|
Made some initial tweaks, discussion above. Feel free to mark whatever resolved if you agree with changes. I suppose the last holdup is the "point in polygon" note that I'd be stuck on. |
Closes #2532.