Add Layer and Artboard node definitions and underlying data structures (#1204)

* Add basic node defenitions

* Code review

* change widget code

* Artboard node changes

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube
2023-05-09 21:57:22 +01:00
committed by Keavon Chambers
parent 7e1b452757
commit 4e0c673a35
12 changed files with 295 additions and 36 deletions

View File

@@ -505,6 +505,30 @@ impl NodeNetwork {
network: self,
}
}
pub fn is_acyclic(&self) -> bool {
let mut dependencies: HashMap<u64, Vec<u64>> = HashMap::new();
for (node_id, node) in &self.nodes {
dependencies.insert(
*node_id,
node.inputs
.iter()
.filter_map(|input| if let NodeInput::Node { node_id: ref_id, .. } = input { Some(*ref_id) } else { None })
.collect(),
);
}
while !dependencies.is_empty() {
let Some((&disconnected, _)) = dependencies.iter().find(|(_, l)| l.is_empty()) else {
error!("Dependencies {dependencies:?}");
return false
};
dependencies.remove(&disconnected);
for connections in dependencies.values_mut() {
connections.retain(|&id| id != disconnected);
}
}
true
}
}
/// Functions for compiling the network
@@ -762,19 +786,16 @@ impl NodeNetwork {
self.nodes.retain(|_, node| !matches!(node.implementation, DocumentNodeImplementation::Extract));
for (_, node) in &mut extraction_nodes {
match node.implementation {
DocumentNodeImplementation::Extract => {
assert_eq!(node.inputs.len(), 1);
let NodeInput::Node { node_id, output_index, lambda } = node.inputs.pop().unwrap() else {
panic!("Extract node has no input");
};
assert_eq!(output_index, 0);
assert!(lambda);
let input_node = self.nodes.get_mut(&node_id).unwrap();
node.implementation = DocumentNodeImplementation::Unresolved("graphene_core::value::ValueNode".into());
node.inputs = vec![NodeInput::value(TaggedValue::DocumentNode(input_node.clone()), false)];
}
_ => (),
if let DocumentNodeImplementation::Extract = node.implementation {
assert_eq!(node.inputs.len(), 1);
let NodeInput::Node { node_id, output_index, lambda } = node.inputs.pop().unwrap() else {
panic!("Extract node has no input");
};
assert_eq!(output_index, 0);
assert!(lambda);
let input_node = self.nodes.get_mut(&node_id).unwrap();
node.implementation = DocumentNodeImplementation::Unresolved("graphene_core::value::ValueNode".into());
node.inputs = vec![NodeInput::value(TaggedValue::DocumentNode(input_node.clone()), false)];
}
}
self.nodes.extend(extraction_nodes);

View File

@@ -57,6 +57,9 @@ pub enum TaggedValue {
Segments(Vec<graphene_core::raster::ImageFrame<Color>>),
EditorApi(graphene_core::EditorApi<'static>),
DocumentNode(DocumentNode),
GraphicGroup(graphene_core::GraphicGroup),
Artboard(graphene_core::Artboard),
Optional2IVec2(Option<[glam::IVec2; 2]>),
}
#[allow(clippy::derived_hash_with_manual_eq)]
@@ -88,15 +91,8 @@ impl Hash for TaggedValue {
Self::ImaginateMaskStartingFill(f) => f.hash(state),
Self::ImaginateStatus(s) => s.hash(state),
Self::LayerPath(p) => p.hash(state),
Self::ImageFrame(i) => {
i.image.hash(state);
i.transform.to_cols_array().iter().for_each(|x| x.to_bits().hash(state))
}
Self::VectorData(vector_data) => {
vector_data.subpaths.hash(state);
vector_data.transform.to_cols_array().iter().for_each(|x| x.to_bits().hash(state));
vector_data.style.hash(state);
}
Self::ImageFrame(i) => i.hash(state),
Self::VectorData(vector_data) => vector_data.hash(state),
Self::Fill(fill) => fill.hash(state),
Self::Stroke(stroke) => stroke.hash(state),
Self::VecF32(vec_f32) => vec_f32.iter().for_each(|val| val.to_bits().hash(state)),
@@ -131,6 +127,9 @@ impl Hash for TaggedValue {
}
Self::EditorApi(editor_api) => editor_api.hash(state),
Self::DocumentNode(document_node) => document_node.hash(state),
Self::GraphicGroup(graphic_group) => graphic_group.hash(state),
Self::Artboard(artboard) => artboard.hash(state),
Self::Optional2IVec2(v) => v.hash(state),
}
}
}
@@ -180,6 +179,9 @@ impl<'a> TaggedValue {
TaggedValue::Segments(x) => Box::new(x),
TaggedValue::EditorApi(x) => Box::new(x),
TaggedValue::DocumentNode(x) => Box::new(x),
TaggedValue::GraphicGroup(x) => Box::new(x),
TaggedValue::Artboard(x) => Box::new(x),
TaggedValue::Optional2IVec2(x) => Box::new(x),
}
}
@@ -240,6 +242,9 @@ impl<'a> TaggedValue {
TaggedValue::Segments(_) => concrete!(graphene_core::raster::IndexNode<Vec<graphene_core::raster::ImageFrame<Color>>>),
TaggedValue::EditorApi(_) => concrete!(graphene_core::EditorApi),
TaggedValue::DocumentNode(_) => concrete!(crate::document::DocumentNode),
TaggedValue::GraphicGroup(_) => concrete!(graphene_core::GraphicGroup),
TaggedValue::Artboard(_) => concrete!(graphene_core::Artboard),
TaggedValue::Optional2IVec2(_) => concrete!(Option<[glam::IVec2; 2]>),
}
}
}