highlight node connections directly

This commit is contained in:
Skyler Lehmkuhl 2026-02-20 11:13:34 -05:00
parent 3ca03069ec
commit 7e2f63b62d
3 changed files with 21 additions and 41 deletions

View File

@ -395,6 +395,7 @@ where
src_pos,
dst_pos,
connection_color,
false,
);
}
@ -406,6 +407,8 @@ where
.any_param_type(AnyParameterId::Output(output))
.unwrap();
let connection_color = port_type.data_type_color(user_state);
let highlighted =
self.highlighted_connection == Some((input, output));
// outputs can't be wide yet so this is fine.
let src_pos = port_locations[&AnyParameterId::Output(output)][0];
let dst_pos = conn_locations[&input][hook_n];
@ -415,6 +418,7 @@ where
src_pos,
dst_pos,
connection_color,
highlighted,
);
}
}
@ -586,10 +590,16 @@ fn draw_connection(
src_pos: Pos2,
dst_pos: Pos2,
color: Color32,
highlighted: bool,
) {
let (width, draw_color) = if highlighted {
(7.0 * pan_zoom.zoom, Color32::from_rgb(100, 220, 100))
} else {
(5.0 * pan_zoom.zoom, color)
};
let connection_stroke = egui::Stroke {
width: 5.0 * pan_zoom.zoom,
color,
width,
color: draw_color,
};
let control_scale = ((dst_pos.x - src_pos.x) * pan_zoom.zoom / 2.0).max(30.0 * pan_zoom.zoom);

View File

@ -31,6 +31,10 @@ pub struct GraphEditorState<NodeData, DataType, ValueType, NodeTemplate, UserSta
pub node_finder: Option<NodeFinder<NodeTemplate>>,
/// The panning of the graph viewport.
pub pan_zoom: PanZoom,
/// A connection to highlight (e.g. as an insertion target during node drag).
/// Stored as (InputId, OutputId). Not serialized.
#[cfg_attr(feature = "persistence", serde(skip))]
pub highlighted_connection: Option<(InputId, OutputId)>,
pub _user_state: PhantomData<fn() -> UserState>,
}
@ -57,6 +61,7 @@ impl<NodeData, DataType, ValueType, NodeKind, UserState> Default
node_positions: Default::default(),
node_finder: Default::default(),
pan_zoom: Default::default(),
highlighted_connection: Default::default(),
_user_state: Default::default(),
}
}

View File

@ -1128,36 +1128,6 @@ impl NodeGraphPane {
best.map(|(input, output, src, dst, _)| (input, output, src, dst))
}
/// Draw a highlight over a connection to indicate insertion target.
/// src/dst are in graph space — converted to screen space here.
fn draw_connection_highlight(
ui: &egui::Ui,
src_graph: egui::Pos2,
dst_graph: egui::Pos2,
zoom: f32,
pan: egui::Vec2,
editor_offset: egui::Vec2,
) {
// Convert graph space to screen space
let to_screen = |p: egui::Pos2| -> egui::Pos2 {
egui::pos2(p.x * zoom + pan.x + editor_offset.x, p.y * zoom + pan.y + editor_offset.y)
};
let src = to_screen(src_graph);
let dst = to_screen(dst_graph);
let control_scale = ((dst.x - src.x) / 2.0).max(30.0 * zoom);
let src_ctrl = egui::pos2(src.x + control_scale, src.y);
let dst_ctrl = egui::pos2(dst.x - control_scale, dst.y);
let bezier = egui::epaint::CubicBezierShape::from_points_stroke(
[src, src_ctrl, dst_ctrl, dst],
false,
egui::Color32::TRANSPARENT,
egui::Stroke::new(7.0 * zoom, egui::Color32::from_rgb(100, 220, 100)),
);
ui.painter().add(bezier);
}
/// Execute the insert-node-on-connection action
fn execute_insert_on_connection(
&mut self,
@ -3103,21 +3073,16 @@ impl crate::panes::PaneRenderer for NodeGraphPane {
if let Some(dragged) = self.dragging_node {
if primary_down {
// Still dragging — check for nearby compatible connection
if let Some((input_id, output_id, src_graph, dst_graph)) = self.find_insert_target(dragged) {
if let Some((input_id, output_id, _src_graph, _dst_graph)) = self.find_insert_target(dragged) {
self.insert_target = Some((input_id, output_id));
Self::draw_connection_highlight(
ui,
src_graph,
dst_graph,
self.state.pan_zoom.zoom,
self.state.pan_zoom.pan,
rect.min.to_vec2(),
);
self.state.highlighted_connection = Some((input_id, output_id));
} else {
self.insert_target = None;
self.state.highlighted_connection = None;
}
} else {
// Drag ended — execute insertion if we have a target
self.state.highlighted_connection = None;
if let Some((target_input, target_output)) = self.insert_target.take() {
self.execute_insert_on_connection(dragged, target_input, target_output, shared);
}