Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ impl NodeNetworkInterface {

let export_name = if !export_name.is_empty() {
export_name
} else if let Some(export_type_name) = input_type.compiled_nested_type().map(|nested| nested.to_string()) {
} else if let Some(export_type_name) = input_type.compiled_nested_type().map(ToString::to_string) {
export_type_name
} else {
format!("Export #{}", export_index)
Expand All @@ -658,12 +658,19 @@ impl NodeNetworkInterface {
}
};

let valid_types = self.potential_valid_input_types(input_connector, network_path).iter().map(ToString::to_string).collect::<Vec<_>>();
let valid_types = {
// Dedupe while preserving order
let mut found = HashSet::new();
valid_types.into_iter().filter(|s| found.insert(s.clone())).collect::<Vec<_>>()
};

Some(FrontendGraphInput {
data_type,
resolved_type,
name,
description,
valid_types: self.potential_valid_input_types(input_connector, network_path).iter().map(|ty| ty.to_string()).collect(),
valid_types,
connected_to,
})
}
Expand Down Expand Up @@ -698,7 +705,7 @@ impl NodeNetworkInterface {

let import_name = if !import_name.is_empty() {
import_name
} else if let Some(import_type_name) = output_type.compiled_nested_type().map(|nested| nested.to_string()) {
} else if let Some(import_type_name) = output_type.compiled_nested_type().map(ToString::to_string) {
import_type_name
} else {
format!("Import #{}", import_index)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ impl TypeSource {
/// The type to display in the tooltip label.
pub fn resolved_type_tooltip_string(&self) -> String {
match self {
TypeSource::Compiled(compiled_type) => format!("Data Type: {:?}", compiled_type.nested_type().to_string()),
TypeSource::TaggedValue(value_type) => format!("Data Type: {:?}", value_type.nested_type().to_string()),
TypeSource::Compiled(compiled_type) => format!("Data Type: {}", compiled_type.nested_type()),
TypeSource::TaggedValue(value_type) => format!("Data Type: {}", value_type.nested_type()),
TypeSource::Unknown => "Unknown Data Type".to_string(),
TypeSource::Invalid => "Invalid Type Combination".to_string(),
TypeSource::Error(_) => "Error Getting Data Type".to_string(),
Expand Down Expand Up @@ -180,7 +180,7 @@ impl NodeNetworkInterface {
self.input_type_not_invalid(input_connector, network_path)
}

// Gets the default tagged value for an input. If its not compiled, then it tries to get a valid type. If there are no valid types, then it picks a random implementation
/// Gets the default tagged value for an input. If its not compiled, then it tries to get a valid type. If there are no valid types, then it picks a random implementation.
pub fn tagged_value_from_input(&mut self, input_connector: &InputConnector, network_path: &[NodeId]) -> TaggedValue {
let guaranteed_type = match self.input_type(input_connector, network_path) {
TypeSource::Compiled(compiled) => compiled,
Expand All @@ -190,12 +190,12 @@ impl NodeNetworkInterface {
// TODO: Add a NodeInput::Indeterminate which can be resolved at compile time to be any type that prevents an error. This may require bidirectional typing.
self.complete_valid_input_types(input_connector, network_path)
.into_iter()
.min_by_key(|ty| ty.nested_type().to_string())
.min_by_key(|ty| ty.nested_type().identifier_name())
// Pick a random type from the potential valid types
.or_else(|| {
self.potential_valid_input_types(input_connector, network_path)
.into_iter()
.min_by_key(|ty| ty.nested_type().to_string())
.min_by_key(|ty| ty.nested_type().identifier_name())
}).unwrap_or(concrete!(()))
}
TypeSource::Error(e) => {
Expand Down
17 changes: 11 additions & 6 deletions node-graph/graph-craft/src/proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,14 @@ impl TypingContext {
.into_iter()
.chain(&inputs)
.enumerate()
.filter_map(|(i, t)| if i == 0 { None } else { Some(format!("• Input {}: {t}", i + convert_node_index_offset)) })
.filter_map(|(i, t)| {
if i == 0 {
None
} else {
let number = i + convert_node_index_offset;
Some(format!("• Input {number}: {t}"))
}
})
.collect::<Vec<_>>()
.join("\n");
Err(vec![GraphError::new(node, GraphErrorType::InvalidImplementations { inputs, error_inputs })])
Expand All @@ -821,13 +828,13 @@ impl TypingContext {
return Ok(node_io.clone());
}
}
let inputs = [call_argument].into_iter().chain(&inputs).map(|t| t.to_string()).collect::<Vec<_>>().join(", ");
let inputs = [call_argument].into_iter().chain(&inputs).map(ToString::to_string).collect::<Vec<_>>().join(", ");
let valid = valid_output_types.into_iter().cloned().collect();
Err(vec![GraphError::new(node, GraphErrorType::MultipleImplementations { inputs, valid })])
}

_ => {
let inputs = [call_argument].into_iter().chain(&inputs).map(|t| t.to_string()).collect::<Vec<_>>().join(", ");
let inputs = [call_argument].into_iter().chain(&inputs).map(ToString::to_string).collect::<Vec<_>>().join(", ");
let valid = valid_output_types.into_iter().cloned().collect();
Err(vec![GraphError::new(node, GraphErrorType::MultipleImplementations { inputs, valid })])
}
Expand Down Expand Up @@ -871,9 +878,7 @@ fn check_generic(types: &NodeIOTypes, input: &Type, parameters: &[Type], generic
/// Returns a list of all generic types used in the node
fn replace_generics(types: &mut NodeIOTypes, lookup: &HashMap<String, Type>) {
let replace = |ty: &Type| {
let Type::Generic(ident) = ty else {
return None;
};
let Type::Generic(ident) = ty else { return None };
lookup.get(ident.as_ref()).cloned()
};
types.call_argument.replace_nested(replace);
Expand Down
67 changes: 26 additions & 41 deletions node-graph/libraries/core-types/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,10 @@ impl NodeIOTypes {

impl std::fmt::Debug for NodeIOTypes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(
"node({}) → {}",
[&self.call_argument].into_iter().chain(&self.inputs).map(|input| input.to_string()).collect::<Vec<_>>().join(", "),
self.return_value
))
let inputs = self.inputs.iter().map(ToString::to_string).collect::<Vec<_>>().join(", ");
let return_value = &self.return_value;
let call_argument = &self.call_argument;
f.write_fmt(format_args!("({inputs}) → {return_value} called with {call_argument}"))
}
}

Expand Down Expand Up @@ -202,7 +201,7 @@ impl std::hash::Hash for TypeDescriptor {

impl std::fmt::Display for TypeDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let text = make_type_user_readable(&format_type(&self.name));
let text = make_type_user_readable(&simplify_identifier_name(&self.name));
write!(f, "{text}")
}
}
Expand Down Expand Up @@ -337,15 +336,17 @@ impl Type {
}
}

pub fn to_cow_string(&self) -> Cow<'static, str> {
pub fn identifier_name(&self) -> String {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for the changed return type here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a change, one unused function is deleted and another new function is added in the same location.

match self {
Type::Generic(name) => name.clone(),
_ => Cow::Owned(self.to_string()),
Type::Generic(name) => name.to_string(),
Type::Concrete(ty) => simplify_identifier_name(&ty.name),
Type::Fn(call_arg, return_value) => format!("{} called with {}", return_value.identifier_name(), call_arg.identifier_name()),
Type::Future(ty) => ty.identifier_name(),
}
}
}

pub fn format_type(ty: &str) -> String {
pub fn simplify_identifier_name(ty: &str) -> String {
ty.split('<')
.map(|path| path.split(',').map(|path| path.split("::").last().unwrap_or(path)).collect::<Vec<_>>().join(","))
.collect::<Vec<_>>()
Expand All @@ -361,42 +362,26 @@ pub fn make_type_user_readable(ty: &str) -> String {

impl std::fmt::Debug for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let text = match self {
Self::Generic(name) => name.to_string(),
#[cfg(feature = "type_id_logging")]
Self::Concrete(ty) => format!("Concrete<{}, {:?}>", ty.name, ty.id),
#[cfg(not(feature = "type_id_logging"))]
Self::Concrete(ty) => format_type(&ty.name),
Self::Fn(call_arg, return_value) => format!("{return_value:?} called with {call_arg:?}"),
Self::Future(ty) => format!("{ty:?}"),
};
let text = make_type_user_readable(&text);
write!(f, "{text}")
write!(f, "{self}")
}
}

// Display
impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self == &concrete!(glam::DVec2) {
return write!(f, "vec2");
}
if self == &concrete!(glam::DAffine2) {
return write!(f, "transform");
}
if self == &concrete!(Footprint) {
return write!(f, "footprint");
}
if self == &concrete!(&str) || self == &concrete!(String) {
return write!(f, "string");
}
use glam::*;

let text = match self {
Type::Generic(name) => name.to_string(),
Type::Concrete(ty) => format_type(&ty.name),
Type::Fn(call_arg, return_value) => format!("{return_value} called with {call_arg}"),
Type::Future(ty) => ty.to_string(),
};
let text = make_type_user_readable(&text);
write!(f, "{text}")
match self {
Type::Generic(name) => write!(f, "{}", make_type_user_readable(name)),
Type::Concrete(ty) => match () {
() if self == &concrete!(DVec2) || self == &concrete!(Vec2) || self == &concrete!(IVec2) || self == &concrete!(UVec2) => write!(f, "Vec2"),
() if self == &concrete!(glam::DAffine2) => write!(f, "Transform"),
() if self == &concrete!(Footprint) => write!(f, "Footprint"),
() if self == &concrete!(&str) || self == &concrete!(String) => write!(f, "String"),
_ => write!(f, "{}", make_type_user_readable(&simplify_identifier_name(&ty.name))),
},
Type::Fn(call_arg, return_value) => write!(f, "{return_value} called with {call_arg}"),
Type::Future(ty) => write!(f, "{ty}"),
}
}
}
6 changes: 3 additions & 3 deletions node-graph/preprocessor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn generate_node_substitutions() -> HashMap<ProtoNodeIdentifier, DocumentNod
let id = id.clone();

let NodeMetadata { fields, .. } = metadata;
let Some(implementations) = &node_registry.get(&id) else { continue };
let Some(implementations) = node_registry.get(&id) else { continue };
let valid_call_args: HashSet<_> = implementations.iter().map(|(_, node_io)| node_io.call_argument.clone()).collect();
let first_node_io = implementations.first().map(|(_, node_io)| node_io).unwrap_or(const { &NodeIOTypes::empty() });
let mut node_io_types = vec![HashSet::new(); fields.len()];
Expand Down Expand Up @@ -69,8 +69,8 @@ pub fn generate_node_substitutions() -> HashMap<ProtoNodeIdentifier, DocumentNod
let input_ty = input.nested_type();
let mut inputs = vec![NodeInput::import(input.clone(), i)];

let into_node_identifier = ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::IntoNode<{}>", input_ty.clone()));
let convert_node_identifier = ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::ConvertNode<{}>", input_ty.clone()));
let into_node_identifier = ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::IntoNode<{}>", input_ty.identifier_name()));
let convert_node_identifier = ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::ConvertNode<{}>", input_ty.identifier_name()));

let proto_node = if into_node_registry.keys().any(|ident: &ProtoNodeIdentifier| ident.as_str() == into_node_identifier.as_str()) {
generated_nodes += 1;
Expand Down
Loading