| use graph_craft::document::value::*; |
| use graph_craft::document::*; |
| use graph_craft::proto::RegistryValueSource; |
| use graph_craft::{ProtoNodeIdentifier, concrete}; |
| use graphene_std::registry::*; |
| use graphene_std::*; |
| use std::collections::{HashMap, HashSet}; |
|
|
| pub fn expand_network(network: &mut NodeNetwork, substitutions: &HashMap<String, DocumentNode>) { |
| if network.generated { |
| return; |
| } |
|
|
| for node in network.nodes.values_mut() { |
| match &mut node.implementation { |
| DocumentNodeImplementation::Network(node_network) => expand_network(node_network, substitutions), |
| DocumentNodeImplementation::ProtoNode(proto_node_identifier) => { |
| if let Some(new_node) = substitutions.get(proto_node_identifier.name.as_ref()) { |
| node.implementation = new_node.implementation.clone(); |
| } |
| } |
| DocumentNodeImplementation::Extract => (), |
| } |
| } |
| } |
|
|
| pub fn generate_node_substitutions() -> HashMap<String, DocumentNode> { |
| let mut custom = HashMap::new(); |
| let node_registry = graphene_core::registry::NODE_REGISTRY.lock().unwrap(); |
| for (id, metadata) in graphene_core::registry::NODE_METADATA.lock().unwrap().iter() { |
| let id = id.clone(); |
|
|
| let NodeMetadata { fields, .. } = metadata; |
| let Some(implementations) = &node_registry.get(&id) else { continue }; |
| let valid_inputs: 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()]; |
| for (_, node_io) in implementations.iter() { |
| for (i, ty) in node_io.inputs.iter().enumerate() { |
| node_io_types[i].insert(ty.clone()); |
| } |
| } |
| let mut input_type = &first_node_io.call_argument; |
| if valid_inputs.len() > 1 { |
| input_type = &const { generic!(D) }; |
| } |
|
|
| let inputs: Vec<_> = node_inputs(fields, first_node_io); |
| let input_count = inputs.len(); |
| let network_inputs = (0..input_count).map(|i| NodeInput::node(NodeId(i as u64), 0)).collect(); |
|
|
| let identity_node = ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode"); |
|
|
| let into_node_registry = &interpreted_executor::node_registry::NODE_REGISTRY; |
|
|
| let mut generated_nodes = 0; |
| let mut nodes: HashMap<_, _, _> = node_io_types |
| .iter() |
| .enumerate() |
| .map(|(i, inputs)| { |
| ( |
| NodeId(i as u64), |
| match inputs.len() { |
| 1 if false => { |
| let input = inputs.iter().next().unwrap(); |
| let input_ty = input.nested_type(); |
|
|
| let into_node_identifier = ProtoNodeIdentifier { |
| name: format!("graphene_core::ops::IntoNode<{}>", input_ty.clone()).into(), |
| }; |
| let convert_node_identifier = ProtoNodeIdentifier { |
| name: format!("graphene_core::ops::ConvertNode<{}>", input_ty.clone()).into(), |
| }; |
|
|
| let proto_node = if into_node_registry.keys().any(|ident: &ProtoNodeIdentifier| ident.name.as_ref() == into_node_identifier.name.as_ref()) { |
| generated_nodes += 1; |
| into_node_identifier |
| } else if into_node_registry.keys().any(|ident| ident.name.as_ref() == convert_node_identifier.name.as_ref()) { |
| generated_nodes += 1; |
| convert_node_identifier |
| } else { |
| identity_node.clone() |
| }; |
|
|
| DocumentNode { |
| inputs: vec![NodeInput::network(input.clone(), i)], |
| |
| implementation: DocumentNodeImplementation::ProtoNode(proto_node), |
| visible: true, |
| ..Default::default() |
| } |
| } |
| _ => DocumentNode { |
| inputs: vec![NodeInput::network(generic!(X), i)], |
| implementation: DocumentNodeImplementation::ProtoNode(identity_node.clone()), |
| visible: false, |
| ..Default::default() |
| }, |
| }, |
| ) |
| }) |
| .collect(); |
|
|
| if generated_nodes == 0 { |
| continue; |
| } |
|
|
| let document_node = DocumentNode { |
| inputs: network_inputs, |
| manual_composition: Some(input_type.clone()), |
| implementation: DocumentNodeImplementation::ProtoNode(id.clone().into()), |
| visible: true, |
| skip_deduplication: false, |
| ..Default::default() |
| }; |
|
|
| nodes.insert(NodeId(input_count as u64), document_node); |
|
|
| let node = DocumentNode { |
| inputs, |
| manual_composition: Some(input_type.clone()), |
| implementation: DocumentNodeImplementation::Network(NodeNetwork { |
| exports: vec![NodeInput::Node { |
| node_id: NodeId(input_count as u64), |
| output_index: 0, |
| lambda: false, |
| }], |
| nodes, |
| scope_injections: Default::default(), |
| generated: true, |
| }), |
| visible: true, |
| skip_deduplication: false, |
| ..Default::default() |
| }; |
|
|
| custom.insert(id.clone(), node); |
| } |
|
|
| custom |
| } |
|
|
| pub fn node_inputs(fields: &[registry::FieldMetadata], first_node_io: &NodeIOTypes) -> Vec<NodeInput> { |
| fields |
| .iter() |
| .zip(first_node_io.inputs.iter()) |
| .enumerate() |
| .map(|(index, (field, node_io_ty))| { |
| let ty = field.default_type.as_ref().unwrap_or(node_io_ty); |
| let exposed = if index == 0 { *ty != fn_type_fut!(Context, ()) } else { field.exposed }; |
|
|
| match field.value_source { |
| RegistryValueSource::None => {} |
| RegistryValueSource::Default(data) => return NodeInput::value(TaggedValue::from_primitive_string(data, ty).unwrap_or(TaggedValue::None), exposed), |
| RegistryValueSource::Scope(data) => return NodeInput::scope(Cow::Borrowed(data)), |
| }; |
|
|
| if let Some(type_default) = TaggedValue::from_type(ty) { |
| return NodeInput::value(type_default, exposed); |
| } |
| NodeInput::value(TaggedValue::None, true) |
| }) |
| .collect() |
| } |
|
|