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) { 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 { 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)], // manual_composition: Some(fn_input.clone()), 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 { 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() }