mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
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:
committed by
Keavon Chambers
parent
7e1b452757
commit
4e0c673a35
@@ -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);
|
||||
|
||||
@@ -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]>),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user