Multiple improvements

This commit is contained in:
Setzer22 2022-06-09 21:25:25 +02:00
parent 316baf91c7
commit d8189997ce
3 changed files with 67 additions and 42 deletions

View File

@ -15,11 +15,17 @@ pub type PortLocations = std::collections::HashMap<AnyParameterId, Pos2>;
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum NodeResponse<UserResponse: UserResponseTrait> { pub enum NodeResponse<UserResponse: UserResponseTrait> {
ConnectEventStarted(NodeId, AnyParameterId), ConnectEventStarted(NodeId, AnyParameterId),
ConnectEventEnded(AnyParameterId), ConnectEventEnded {
output: OutputId,
input: InputId,
},
CreatedNode(NodeId), CreatedNode(NodeId),
SelectNode(NodeId), SelectNode(NodeId),
DeleteNode(NodeId), DeleteNode(NodeId),
DisconnectEvent(InputId), DisconnectEvent {
output: OutputId,
input: InputId,
},
/// Emitted when a node is interacted with, and should be raised /// Emitted when a node is interacted with, and should be raised
RaiseNode(NodeId), RaiseNode(NodeId),
User(UserResponse), User(UserResponse),
@ -183,24 +189,8 @@ where
NodeResponse::ConnectEventStarted(node_id, port) => { NodeResponse::ConnectEventStarted(node_id, port) => {
self.connection_in_progress = Some((node_id, port)); self.connection_in_progress = Some((node_id, port));
} }
NodeResponse::ConnectEventEnded(locator) => { NodeResponse::ConnectEventEnded { input, output } => {
let in_out = match ( self.graph.add_connection(output, input)
self.connection_in_progress
.map(|(_node, param)| param)
.take()
.expect("Cannot end drag without in-progress connection."),
locator,
) {
(AnyParameterId::Input(input), AnyParameterId::Output(output))
| (AnyParameterId::Output(output), AnyParameterId::Input(input)) => {
Some((input, output))
}
_ => None,
};
if let Some((input, output)) = in_out {
self.graph.add_connection(output, input)
}
} }
NodeResponse::CreatedNode(_) => { NodeResponse::CreatedNode(_) => {
//Convenience NodeResponse for users //Convenience NodeResponse for users
@ -213,9 +203,7 @@ where
extra_responses.extend( extra_responses.extend(
removed removed
.into_iter() .into_iter()
.map(|x| x.0) .map(|(input, output)| NodeResponse::DisconnectEvent { input, output }),
.into_iter()
.map(NodeResponse::DisconnectEvent),
); );
self.node_positions.remove(node_id); self.node_positions.remove(node_id);
// Make sure to not leave references to old nodes hanging // Make sure to not leave references to old nodes hanging
@ -224,15 +212,11 @@ where
} }
self.node_order.retain(|id| *id != node_id); self.node_order.retain(|id| *id != node_id);
} }
NodeResponse::DisconnectEvent(input_id) => { NodeResponse::DisconnectEvent { input, output } => {
let corresp_output = self let other_node = self.graph.get_input(input).node();
.graph self.graph.remove_connection(input);
.connection(input_id)
.expect("Connection data should be valid");
let other_node = self.graph.get_input(input_id).node();
self.graph.remove_connection(input_id);
self.connection_in_progress = self.connection_in_progress =
Some((other_node, AnyParameterId::Output(corresp_output))); Some((other_node, AnyParameterId::Output(output)));
} }
NodeResponse::RaiseNode(node_id) => { NodeResponse::RaiseNode(node_id) => {
let old_pos = self let old_pos = self
@ -375,6 +359,7 @@ where
.text_style(TextStyle::Button) .text_style(TextStyle::Button)
.color(text_color), .color(text_color),
)); ));
ui.add_space(8.0); // The size of the little cross icon
}); });
ui.add_space(margin.y); ui.add_space(margin.y);
title_height = ui.min_size().y; title_height = ui.min_size().y;
@ -460,7 +445,14 @@ where
if resp.drag_started() { if resp.drag_started() {
if is_connected_input { if is_connected_input {
responses.push(NodeResponse::DisconnectEvent(param_id.assume_input())); let input = param_id.assume_input();
let corresp_output = graph
.connection(input)
.expect("Connection data should be valid");
responses.push(NodeResponse::DisconnectEvent {
input: param_id.assume_input(),
output: corresp_output,
});
} else { } else {
responses.push(NodeResponse::ConnectEventStarted(node_id, param_id)); responses.push(NodeResponse::ConnectEventStarted(node_id, param_id));
} }
@ -473,7 +465,13 @@ where
&& resp.hovered() && resp.hovered()
&& ui.input().pointer.any_released() && ui.input().pointer.any_released()
{ {
responses.push(NodeResponse::ConnectEventEnded(param_id)); match (param_id, origin_param) {
(AnyParameterId::Input(input), AnyParameterId::Output(output))
| (AnyParameterId::Output(output), AnyParameterId::Input(input)) => {
responses.push(NodeResponse::ConnectEventEnded { input, output });
}
_ => { /* Ignore in-in or out-out connections */ }
}
} }
} }
} }
@ -532,7 +530,7 @@ where
} }
// Draw the background shape. // Draw the background shape.
// NOTE: This code is a bit more involve than it needs to be because egui // NOTE: This code is a bit more involved than it needs to be because egui
// does not support drawing rectangles with asymmetrical round corners. // does not support drawing rectangles with asymmetrical round corners.
let (shape, outline) = { let (shape, outline) = {

View File

@ -16,11 +16,38 @@ pub trait WidgetValueTrait {
/// [`Graph`]. This trait tells the library how to visually expose data types /// [`Graph`]. This trait tells the library how to visually expose data types
/// to the user. /// to the user.
pub trait DataTypeTrait<UserState>: PartialEq + Eq { pub trait DataTypeTrait<UserState>: PartialEq + Eq {
// The associated port color of this datatype /// The associated port color of this datatype
fn data_type_color(&self, user_state: &UserState) -> egui::Color32; fn data_type_color(&self, user_state: &UserState) -> egui::Color32;
// The name of this datatype /// The name of this datatype. Return type is specified as Cow<str> because
fn name(&self) -> &str; /// some implementations will need to allocate a new string to provide an
/// answer while others won't.
///
/// ## Example (borrowed value)
/// Use this when you can get the name of the datatype from its fields or as
/// a &'static str. Prefer this method when possible.
/// ```rust
/// pub struct DataType { name: String }
///
/// impl DataTypeTrait<()> for DataType {
/// fn name(&self) -> std::borrow::Cow<str> {
/// Cow::Borrowed(&self.name)
/// }
/// }
/// ```
///
/// ## Example (owned value)
/// Use this when you can't derive the name of the datatype from its fields.
/// ```rust
/// pub struct DataType { some_tag: i32 }
///
/// impl DataTypeTrait<()> for DataType {
/// fn name(&self) -> std::borrow::Cow<str> {
/// Cow::Owned(format!("Super amazing type #{}", self.some_tag))
/// }
/// }
/// ```
fn name(&self) -> std::borrow::Cow<str>;
} }
/// This trait must be implemented for the `NodeData` generic parameter of the /// This trait must be implemented for the `NodeData` generic parameter of the

View File

@ -1,4 +1,4 @@
use std::collections::HashMap; use std::{borrow::Cow, collections::HashMap};
use eframe::egui::{self, DragValue, TextStyle}; use eframe::egui::{self, DragValue, TextStyle};
use egui_node_graph::*; use egui_node_graph::*;
@ -97,10 +97,10 @@ impl DataTypeTrait<MyGraphState> for MyDataType {
} }
} }
fn name(&self) -> &str { fn name(&self) -> Cow<'_, str> {
match self { match self {
MyDataType::Scalar => "scalar", MyDataType::Scalar => Cow::Borrowed("scalar"),
MyDataType::Vec2 => "2d vector", MyDataType::Vec2 => Cow::Borrowed("2d vector"),
} }
} }
} }
@ -383,7 +383,7 @@ impl eframe::App for NodeGraphExample {
Err(err) => format!("Execution error: {}", err), Err(err) => format!("Execution error: {}", err),
}; };
ctx.debug_painter().text( ctx.debug_painter().text(
egui::pos2(10.0, 10.0), egui::pos2(10.0, 35.0),
egui::Align2::LEFT_TOP, egui::Align2::LEFT_TOP,
text, text,
TextStyle::Button.resolve(&ctx.style()), TextStyle::Button.resolve(&ctx.style()),