This PR will migrate click detection, translation/scale and wire calculations from Graph.svelte to the NodeGraphMessageHandler. Instead of relying on the DOM and JavaScript click detection to get positions for various elements and send messages via editor.handle, all logic and calculations will be performed in the NodeGraphMessageHandler. Since Rust only has access to the node and wire data, all positioning functions that previously used the DOM will have to be recreated. This includes
closest() which will calculate the bounding box for each node using [SDFs](Rounding Corners in SDFs) and offscreen text rendering to check if a click event occurred within a node or node input
getBoundingClientRect(), which will get the position of node inputs and outputs in node graph coordinates
a new function NodeGraphToPixelCoordinates(), which will convert the node graph position to pixel coordinates that can be compared with the click event
Another important concept will be to store positions in node graph coordinates, and derive pixel coordinates when needed using the current transform (position/scale). This should solve a current issue where scaling the node graph breaks the automatic node insertion on a wire.
Other features
Autopan when cursor is node is being dragged and cursor goes outside nod graph
Make scroll bars functional and display scroll bars based on current transform
Move blue selection box highlighting nodes before they are selected to Rust
Cache ClickTargets (HashMap<NodeId, ClickTarget>) and keep them in sync with the visual nodes by making inputs, metadata (position), and is_layer, and eventually name private fields, and creating getters/setters that keep the cache in sync. This removes the 50ms per frame requires to calculate bounding boxes.
Cache bounding box for viewport artwork
Also cache the bounding box around the entire node network, and convert to viewport coordinates when rendering scrollbars. Keep all coordinates in node graph coordinates, and only use the transform to convert mouse position to node graph coordinates, or converting the bounding box to viewport coordinates.
Issues:
Clicking CreateComputePass crashes, likely an issue caused by my last PR
[x] Pressing Shift causes the last box selection's blue box to reappear for some reason, as does right-clicking
[x] Ctrl+0 (or View > Zoom to Fit All) just teleports the origin to the top left but doesn't center the entire node graph contents like it should
[x] Numpad Period (or View > Zoom to Fit Selection) just seems to zoom out a little bit rather than zooming to center and fit the selected nodes (it's nice to see that the Zoom In and Zoom Out buttons work though!)
[x] We'll want to gray out View > Tilt and View > Reset Tilt
[x] Ctrl+Z doesnt add click targets back
[x] // TODO: Find a better way to update click targets when undoing/redoing
[x] Save node_graph_transform: PTZ for every network
Closes #1777 and (presumably) fixes #1548.
This PR will migrate click detection, translation/scale and wire calculations from Graph.svelte to the NodeGraphMessageHandler. Instead of relying on the DOM and JavaScript click detection to get positions for various elements and send messages via editor.handle, all logic and calculations will be performed in the NodeGraphMessageHandler. Since Rust only has access to the node and wire data, all positioning functions that previously used the DOM will have to be recreated. This includes
closest()
which will calculate the bounding box for each node using [SDFs](Rounding Corners in SDFs) and offscreen text rendering to check if a click event occurred within a node or node inputgetBoundingClientRect()
, which will get the position of node inputs and outputs in node graph coordinatesa new function
NodeGraphToPixelCoordinates()
, which will convert the node graph position to pixel coordinates that can be compared with the click eventAnother important concept will be to store positions in node graph coordinates, and derive pixel coordinates when needed using the current transform (position/scale). This should solve a current issue where scaling the node graph breaks the automatic node insertion on a wire.
Other features
HashMap<NodeId, ClickTarget>
) and keep them in sync with the visual nodes by making inputs, metadata (position), and is_layer, and eventually name private fields, and creating getters/setters that keep the cache in sync. This removes the 50ms per frame requires to calculate bounding boxes.Issues: