diff --git a/egui_node_graph2/src/editor_ui.rs b/egui_node_graph2/src/editor_ui.rs index 9c3323b..b134ddd 100644 --- a/egui_node_graph2/src/editor_ui.rs +++ b/egui_node_graph2/src/editor_ui.rs @@ -59,7 +59,7 @@ pub enum NodeResponse /// Emitted when a node is interacted with, and should be raised RaiseNode(NodeId), MoveNode { - node: NodeId, + node_id: NodeId, drag_delta: Vec2, }, User(UserResponse), @@ -278,8 +278,8 @@ where if let Some(node_kind) = node_finder.show(ui, all_kinds, user_state) { let new_node = self.graph.add_node( node_kind.node_graph_label(user_state), - node_kind.user_data(user_state), - |graph, node_id| node_kind.build_node(graph, user_state, node_id), + node_kind.node_data(user_state), + |graph, node_id| node_kind.build_node(graph, node_id, user_state), ); self.node_positions.insert( new_node, @@ -468,12 +468,12 @@ where self.node_order.remove(old_pos); self.node_order.push(*node_id); } - NodeResponse::MoveNode { node, drag_delta } => { - self.node_positions[*node] += *drag_delta; + NodeResponse::MoveNode { node_id, drag_delta } => { + self.node_positions[*node_id] += *drag_delta; // Handle multi-node selection movement - if self.selected_nodes.contains(node) && self.selected_nodes.len() > 1 { + if self.selected_nodes.contains(node_id) && self.selected_nodes.len() > 1 { for n in self.selected_nodes.iter().copied() { - if n != *node { + if n != *node_id { self.node_positions[n] += *drag_delta; } } @@ -617,12 +617,8 @@ where ui: &mut Ui, user_state: &mut UserState, ) -> Vec> { - let mut child_ui = ui.child_ui_with_id_source( - Rect::from_min_size(*self.position + self.pan, Self::MAX_NODE_SIZE.into()), - Layout::default(), - self.node_id, - None, - ); + let max_rect = Rect::from_min_size(*self.position + self.pan, Self::MAX_NODE_SIZE.into()); + let mut child_ui = ui.new_child(UiBuilder::new().max_rect(max_rect).id_salt(self.node_id)); Self::show_graph_node(self, pan_zoom, &mut child_ui, user_state) } @@ -666,7 +662,7 @@ where inner_rect.max.x = inner_rect.max.x.max(inner_rect.min.x); inner_rect.max.y = inner_rect.max.y.max(inner_rect.min.y); - let mut child_ui = ui.child_ui(inner_rect, *ui.layout(), None); + let mut child_ui = ui.new_child(UiBuilder::new().max_rect(inner_rect).layout(*ui.layout())); // Get interaction rect from memory, it may expand after the window response on resize. let interaction_rect = ui @@ -697,7 +693,7 @@ where .text_style(TextStyle::Button) .color(text_color), )); - responses.extend(self.graph[self.node_id].user_data.top_bar_ui( + responses.extend(self.graph[self.node_id].node_data.top_bar_ui( ui, self.node_id, self.graph, @@ -709,13 +705,47 @@ where title_height = ui.min_size().y; // First pass: Draw the inner fields. Compute port heights + let outputs = self.graph[self.node_id].outputs.clone(); + for (param_name, param_id) in outputs { + let height_before = ui.min_rect().bottom(); + + ui.horizontal(|ui| { + ui.allocate_space(ui.available_size()); + + responses.extend( + self.graph[self.node_id] + .node_data + .output_ui(ui, self.node_id, ¶m_name, self.graph, user_state) + .into_iter(), + ); + }); + + self.graph[self.node_id].node_data.separator( + ui, + self.node_id, + AnyParameterId::Output(param_id), + self.graph, + user_state, + ); + + let height_after = ui.min_rect().bottom(); + output_port_heights.push((height_before + height_after) / 2.0); + } + + responses.extend(self.graph[self.node_id].node_data.bottom_ui( + ui, + self.node_id, + self.graph, + user_state, + )); + let inputs = self.graph[self.node_id].inputs.clone(); for (param_name, param_id) in inputs { if self.graph[param_id].shown_inline { let height_before = ui.min_rect().bottom(); if self.graph[param_id].max_connections == NonZeroU32::new(1) { - // NOTE: We want to pass the `user_data` to + // NOTE: We want to pass the `node_data` to // `value_widget`, but we can't since that would require // borrowing the graph twice. Here, we make the // assumption that the value is cheaply replaced, and @@ -724,23 +754,27 @@ where // Default, but results in a totally safe alternative. let mut value = std::mem::take(&mut self.graph[param_id].value); + let node_data = &self.graph[self.node_id].node_data; + if !self.graph.connections(param_id).is_empty() { let node_responses = value.value_widget_connected( - ¶m_name, - self.node_id, ui, - user_state, - &self.graph[self.node_id].user_data, + self.node_id, + param_id, + ¶m_name, + node_data, + user_state ); responses.extend(node_responses.into_iter().map(NodeResponse::User)); } else { let node_responses = value.value_widget( - ¶m_name, - self.node_id, ui, - user_state, - &self.graph[self.node_id].user_data, + self.node_id, + param_id, + ¶m_name, + node_data, + user_state ); responses.extend(node_responses.into_iter().map(NodeResponse::User)); @@ -770,7 +804,7 @@ where ui.add_space(missing_space); } - self.graph[self.node_id].user_data.separator( + self.graph[self.node_id].node_data.separator( ui, self.node_id, AnyParameterId::Input(param_id), @@ -783,35 +817,6 @@ where input_port_heights.push((height_before + height_after) / 2.0); } } - - let outputs = self.graph[self.node_id].outputs.clone(); - for (param_name, param_id) in outputs { - let height_before = ui.min_rect().bottom(); - responses.extend( - self.graph[self.node_id] - .user_data - .output_ui(ui, self.node_id, self.graph, user_state, ¶m_name) - .into_iter(), - ); - - self.graph[self.node_id].user_data.separator( - ui, - self.node_id, - AnyParameterId::Output(param_id), - self.graph, - user_state, - ); - - let height_after = ui.min_rect().bottom(); - output_port_heights.push((height_before + height_after) / 2.0); - } - - responses.extend(self.graph[self.node_id].user_data.bottom_ui( - ui, - self.node_id, - self.graph, - user_state, - )); }); // Second pass, iterate again to draw the ports. This happens outside @@ -1074,7 +1079,7 @@ where rect: titlebar_rect, rounding, fill: self.graph[self.node_id] - .user_data + .node_data .titlebar_color(ui, self.node_id, self.graph, user_state) .unwrap_or_else(|| background_color.lighten(0.8)), stroke: Stroke::NONE, @@ -1138,7 +1143,7 @@ where // --- Interaction --- // Titlebar buttons - let can_delete = self.graph.nodes[self.node_id].user_data.can_delete( + let can_delete = self.graph.nodes[self.node_id].node_data.can_delete( self.node_id, self.graph, user_state, @@ -1152,7 +1157,7 @@ where let drag_delta = window_response.drag_delta(); if drag_delta.length_sq() > 0.0 { responses.push(NodeResponse::MoveNode { - node: self.node_id, + node_id: self.node_id, drag_delta, }); responses.push(NodeResponse::RaiseNode(self.node_id)); diff --git a/egui_node_graph2/src/graph.rs b/egui_node_graph2/src/graph.rs index 85c142e..6ae1512 100644 --- a/egui_node_graph2/src/graph.rs +++ b/egui_node_graph2/src/graph.rs @@ -15,7 +15,7 @@ pub struct Node { pub label: String, pub inputs: Vec<(String, InputId)>, pub outputs: Vec<(String, OutputId)>, - pub user_data: NodeData, + pub node_data: NodeData, } /// The three kinds of input params. These describe how the graph must behave diff --git a/egui_node_graph2/src/graph_impls.rs b/egui_node_graph2/src/graph_impls.rs index a117b95..e79d3e0 100644 --- a/egui_node_graph2/src/graph_impls.rs +++ b/egui_node_graph2/src/graph_impls.rs @@ -15,7 +15,7 @@ impl Graph { pub fn add_node( &mut self, label: String, - user_data: NodeData, + node_data: NodeData, f: impl FnOnce(&mut Graph, NodeId), ) -> NodeId { let node_id = self.nodes.insert_with_key(|node_id| { @@ -25,7 +25,7 @@ impl Graph { // These get filled in later by the user function inputs: Vec::default(), outputs: Vec::default(), - user_data, + node_data, } }); @@ -241,14 +241,14 @@ impl Node { pub fn inputs<'a, DataType, DataValue>( &'a self, graph: &'a Graph, - ) -> impl Iterator> + 'a { + ) -> impl Iterator> { self.input_ids().map(|id| graph.get_input(id)) } pub fn outputs<'a, DataType, DataValue>( &'a self, graph: &'a Graph, - ) -> impl Iterator> + 'a { + ) -> impl Iterator> { self.output_ids().map(|id| graph.get_output(id)) } diff --git a/egui_node_graph2/src/traits.rs b/egui_node_graph2/src/traits.rs index 694c090..0ac7f20 100644 --- a/egui_node_graph2/src/traits.rs +++ b/egui_node_graph2/src/traits.rs @@ -21,11 +21,12 @@ pub trait WidgetValueTrait: Default { /// be empty. fn value_widget( &mut self, - param_name: &str, - node_id: NodeId, ui: &mut egui::Ui, - user_state: &mut Self::UserState, + node_id: NodeId, + param_id: InputId, + param_name: &str, node_data: &Self::NodeData, + user_state: &mut Self::UserState, ) -> Vec; /// This method will be called for each input parameter with a widget with a connected @@ -37,11 +38,12 @@ pub trait WidgetValueTrait: Default { /// Shows the input name label by default. fn value_widget_connected( &mut self, - param_name: &str, - _node_id: NodeId, ui: &mut egui::Ui, - _user_state: &mut Self::UserState, + _node_id: NodeId, + _param_id: InputId, + param_name: &str, _node_data: &Self::NodeData, + _user_state: &mut Self::UserState, ) -> Vec { ui.label(param_name); @@ -134,9 +136,9 @@ where &self, ui: &mut egui::Ui, _node_id: NodeId, - _graph: &Graph, - _user_state: &mut Self::UserState, param_name: &str, + _graph: &Graph, + _user_state: &mut Self::UserState ) -> Vec> where Self::Response: UserResponseTrait, @@ -266,7 +268,7 @@ pub trait NodeTemplateTrait: Clone { fn node_graph_label(&self, user_state: &mut Self::UserState) -> String; /// Returns the user data for this node kind. - fn user_data(&self, user_state: &mut Self::UserState) -> Self::NodeData; + fn node_data(&self, user_state: &mut Self::UserState) -> Self::NodeData; /// This function is run when this node kind gets added to the graph. The /// node will be empty by default, and this function can be used to fill its @@ -274,8 +276,8 @@ pub trait NodeTemplateTrait: Clone { fn build_node( &self, graph: &mut Graph, - user_state: &mut Self::UserState, node_id: NodeId, + user_state: &mut Self::UserState ); } diff --git a/egui_node_graph2_example/src/app.rs b/egui_node_graph2_example/src/app.rs index e5daf74..757bd60 100644 --- a/egui_node_graph2_example/src/app.rs +++ b/egui_node_graph2_example/src/app.rs @@ -158,15 +158,15 @@ impl NodeTemplateTrait for MyNodeTemplate { self.node_finder_label(user_state).into() } - fn user_data(&self, _user_state: &mut Self::UserState) -> Self::NodeData { + fn node_data(&self, _user_state: &mut Self::UserState) -> Self::NodeData { MyNodeData { template: *self } } fn build_node( &self, graph: &mut Graph, - _user_state: &mut Self::UserState, node_id: NodeId, + _user_state: &mut Self::UserState ) { // The nodes are created empty by default. This function needs to take // care of creating the desired inputs and outputs based on the template @@ -284,11 +284,12 @@ impl WidgetValueTrait for MyValueType { type NodeData = MyNodeData; fn value_widget( &mut self, - param_name: &str, - _node_id: NodeId, ui: &mut egui::Ui, - _user_state: &mut MyGraphState, + _node_id: NodeId, + _param_id: InputId, + param_name: &str, _node_data: &MyNodeData, + _user_state: &mut MyGraphState ) -> Vec { // This trait is used to tell the library which UI to display for the // inline parameter widgets. @@ -412,7 +413,7 @@ impl eframe::App for NodeGraphExample { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::TopBottomPanel::top("top").show(ctx, |ui| { egui::menu::bar(ui, |ui| { - egui::widgets::global_dark_light_mode_switch(ui); + egui::widgets::global_theme_preference_switch(ui); }); }); let graph_response = egui::CentralPanel::default() @@ -524,7 +525,7 @@ pub fn evaluate_node( let node = &graph[node_id]; let mut evaluator = Evaluator::new(graph, outputs_cache, node_id); - match node.user_data.template { + match node.node_data.template { MyNodeTemplate::AddScalar => { let a = evaluator.input_scalar("A")?; let b = evaluator.input_scalar("B")?;