Remove explicit empty stack nodes (#1445)

* Remove explicit empty stack nodes

* Code review stylistic simplifications

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube 2023-10-29 03:41:31 +00:00 committed by GitHub
parent ceb2f4c13f
commit 380bc19b09
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 24 deletions

View file

@ -1,6 +1,6 @@
use crate::document::value::TaggedValue;
use crate::proto::{ConstructionArgs, ProtoNetwork, ProtoNode, ProtoNodeInput};
use graphene_core::{NodeIdentifier, Type};
use graphene_core::{GraphicGroup, NodeIdentifier, Type};
use dyn_any::{DynAny, StaticType};
use glam::IVec2;
@ -1006,6 +1006,45 @@ impl NodeNetwork {
self.nodes.extend(extraction_nodes);
}
/// Due to the adaptive resolution system, nodes that take a `GraphicGroup` as input must call the upstream node with the `Footprint` parameter.
///
/// However, in the case of the default input, we must insert a node that takes an input of `Footprint` and returns `GraphicGroup::Empty`, in order to satisfy the type system.
/// This is because the standard value node takes in `()`.
pub fn resolve_empty_stacks(&mut self) {
const EMPTY_STACK: &str = "Empty Stack";
let new_id = generate_uuid();
let mut used = false;
// We filter out the newly inserted empty stack in case `resolve_empty_stacks` runs multiple times.
for node in self.nodes.values_mut().filter(|node| node.name != EMPTY_STACK) {
for input in &mut node.inputs {
if matches!(
input,
NodeInput::Value {
tagged_value: TaggedValue::GraphicGroup(GraphicGroup::EMPTY),
..
}
) {
*input = NodeInput::node(new_id, 0);
used = true;
}
}
}
// Only insert the node if necessary.
if used {
let new_node = DocumentNode {
name: EMPTY_STACK.to_string(),
implementation: DocumentNodeImplementation::proto("graphene_core::transform::CullNode<_>"),
manual_composition: Some(concrete!(graphene_core::transform::Footprint)),
inputs: vec![NodeInput::value(TaggedValue::GraphicGroup(graphene_core::GraphicGroup::EMPTY), false)],
..Default::default()
};
self.nodes.insert(new_id, new_node);
}
}
/// Creates a proto network for evaluating each output of this network.
pub fn into_proto_networks(self) -> impl Iterator<Item = ProtoNetwork> {
let mut nodes: Vec<_> = self.nodes.into_iter().map(|(id, node)| (id, node.resolve_proto_node())).collect();
@ -1089,7 +1128,7 @@ mod test {
fn map_ids() {
let mut network = add_network();
network.map_ids(|id| id + 1);
let maped_add = NodeNetwork {
let mapped_add = NodeNetwork {
inputs: vec![1, 1],
outputs: vec![NodeOutput::new(2, 0)],
nodes: [
@ -1116,7 +1155,7 @@ mod test {
.collect(),
..Default::default()
};
assert_eq!(network, maped_add);
assert_eq!(network, mapped_add);
}
#[test]

View file

@ -10,6 +10,7 @@ pub struct Compiler {}
impl Compiler {
pub fn compile(&self, mut network: NodeNetwork) -> Result<impl Iterator<Item = ProtoNetwork>, String> {
println!("flattening");
network.resolve_empty_stacks();
let node_ids = network.nodes.keys().copied().collect::<Vec<_>>();
for id in node_ids {
network.flatten(id);