openfree's picture
Deploy from GitHub repository
2409829 verified
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)],
// 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<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()
}