Skip to content

Commit a2046a5

Browse files
0HyperCubeKeavon
andcommitted
Add basic vector nodes (#1059)
* Add some derives * Allow node_fn with mutable inputs * Add basic vector nodes * Revert elipse tool changes * Fix the elipse tool again * Change spacer width * Bubble serde feature in graph craft --------- Co-authored-by: Keavon Chambers <[email protected]>
1 parent 7e37fb4 commit a2046a5

File tree

22 files changed

+707
-151
lines changed

22 files changed

+707
-151
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

document-legacy/src/document.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::hash::{Hash, Hasher};
2121
/// This does not technically need to be unique globally, only within a folder.
2222
pub type LayerId = u64;
2323

24-
#[derive(Debug, Clone, Deserialize, Serialize, specta::Type)]
24+
#[derive(Debug, Clone, Deserialize, Serialize)]
2525
pub struct Document {
2626
/// The root layer, usually a [FolderLayer](layers::folder_layer::FolderLayer) that contains all other [Layers](layers::layer_info::Layer).
2727
pub root: Layer,

document-legacy/src/layers/folder_layer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
99
/// A layer that encapsulates other layers, including potentially more folders.
1010
/// The contained layers are rendered in the same order they are
1111
/// stored in the [layers](FolderLayer::layers) field.
12-
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Default, specta::Type)]
12+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Default)]
1313
pub struct FolderLayer {
1414
/// The ID that will be assigned to the next layer that is added to the folder
1515
next_assignment_id: LayerId,

document-legacy/src/layers/layer_info.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use glam::{DAffine2, DMat2, DVec2};
1515
use serde::{Deserialize, Serialize};
1616
use std::fmt::Write;
1717

18-
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, specta::Type)]
18+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1919
/// Represents different types of layers.
2020
pub enum LayerDataType {
2121
/// A layer that wraps a [FolderLayer] struct.
@@ -213,7 +213,7 @@ fn return_true() -> bool {
213213
true
214214
}
215215

216-
#[derive(Debug, PartialEq, Deserialize, Serialize, specta::Type)]
216+
#[derive(Debug, PartialEq, Deserialize, Serialize)]
217217
pub struct Layer {
218218
/// Whether the layer is currently visible or hidden.
219219
pub visible: bool,

document-legacy/src/layers/nodegraph_layer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use kurbo::{Affine, BezPath, Shape as KurboShape};
99
use serde::{Deserialize, Serialize};
1010
use std::fmt::Write;
1111

12-
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize, specta::Type)]
12+
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
1313
pub struct NodeGraphFrameLayer {
1414
// Image stored in layer after generation completes
1515
pub mime: String,

document-legacy/src/operation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::collections::hash_map::DefaultHasher;
1313
use std::hash::{Hash, Hasher};
1414

1515
#[repr(C)]
16-
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, specta::Type)]
16+
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
1717
// TODO: Rename all instances of `path` to `layer_path`
1818
/// Operations that can be performed to mutate the document.
1919
pub enum Operation {

editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use graphene_core::raster::color::Color;
1212
use glam::DAffine2;
1313
use serde::{Deserialize, Serialize};
1414

15-
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, specta::Type)]
15+
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
1616
pub struct ArtboardMessageHandler {
1717
pub artboards_document: DocumentLegacy,
1818
pub artboard_ids: Vec<LayerId>,

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl FrontendGraphDataType {
4646
TaggedValue::Image(_) => Self::Raster,
4747
TaggedValue::ImageFrame(_) => Self::Raster,
4848
TaggedValue::Color(_) => Self::Color,
49-
TaggedValue::RcSubpath(_) | TaggedValue::Subpath(_) => Self::Subpath,
49+
TaggedValue::RcSubpath(_) | TaggedValue::Subpath(_) | TaggedValue::VectorData(_) => Self::Subpath,
5050
_ => Self::General,
5151
}
5252
}

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs

Lines changed: 89 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl DocumentInputType {
3232
Self { name, data_type, default }
3333
}
3434

35-
pub const fn _none() -> Self {
35+
pub const fn none() -> Self {
3636
Self {
3737
name: "None",
3838
data_type: FrontendGraphDataType::General,
@@ -589,59 +589,74 @@ fn static_nodes() -> Vec<DocumentNodeType> {
589589
properties: node_properties::add_properties,
590590
},
591591
(*IMAGINATE_NODE).clone(),
592-
/*DocumentNodeType {
593-
name: "Unit Circle Generator",
594-
category: "Vector",
595-
identifier: NodeImplementation::proto("graphene_std::vector::generator_nodes::UnitCircleGenerator", &[]),
596-
inputs: vec![DocumentInputType::none()],
597-
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
598-
properties: node_properties::no_properties,
599-
},
600592
DocumentNodeType {
601-
name: "Unit Square Generator",
593+
name: "Unit Circle Generator",
602594
category: "Vector",
603-
identifier: NodeImplementation::proto("graphene_std::vector::generator_nodes::UnitSquareGenerator", &[]),
595+
identifier: NodeImplementation::proto("graphene_core::vector::generator_nodes::UnitCircleGenerator"),
604596
inputs: vec![DocumentInputType::none()],
605597
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
606598
properties: node_properties::no_properties,
607599
},
608600
DocumentNodeType {
609601
name: "Path Generator",
610602
category: "Vector",
611-
identifier: NodeImplementation::proto("graphene_core::ops::IdNode"),
603+
identifier: NodeImplementation::proto("graphene_core::vector::generator_nodes::PathGenerator"),
612604
inputs: vec![DocumentInputType {
613605
name: "Path Data",
614606
data_type: FrontendGraphDataType::Subpath,
615-
default: NodeInput::value(TaggedValue::Subpath(Subpath::new()), false),
607+
default: NodeInput::value(TaggedValue::Subpath(bezier_rs::Subpath::new(Vec::new(), false)), false),
616608
}],
617609
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
618610
properties: node_properties::no_properties,
619611
},
620612
DocumentNodeType {
621-
name: "Transform Subpath",
613+
name: "Transform",
622614
category: "Vector",
623-
identifier: NodeImplementation::proto("graphene_std::vector::generator_nodes::TransformSubpathNode", &[]),
615+
identifier: NodeImplementation::proto("graphene_core::vector::TransformNode<_, _, _, _>"),
624616
inputs: vec![
625-
DocumentInputType::new("Subpath", TaggedValue::Subpath(Subpath::empty()), true),
626-
DocumentInputType::new("Translation", TaggedValue::DVec2(DVec2::ZERO), false),
627-
DocumentInputType::new("Rotation", TaggedValue::F64(0.), false),
628-
DocumentInputType::new("Scale", TaggedValue::DVec2(DVec2::ONE), false),
629-
DocumentInputType::new("Skew", TaggedValue::DVec2(DVec2::ZERO), false),
617+
DocumentInputType::value("Vector Data", TaggedValue::VectorData(graphene_core::vector::VectorData::empty()), true),
618+
DocumentInputType::value("Translation", TaggedValue::DVec2(DVec2::ZERO), false),
619+
DocumentInputType::value("Rotation", TaggedValue::F64(0.), false),
620+
DocumentInputType::value("Scale", TaggedValue::DVec2(DVec2::ONE), false),
621+
DocumentInputType::value("Skew", TaggedValue::DVec2(DVec2::ZERO), false),
630622
],
631623
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
632624
properties: node_properties::transform_properties,
633625
},
634626
DocumentNodeType {
635-
name: "Blit Subpath",
627+
name: "Fill",
628+
category: "Vector",
629+
identifier: NodeImplementation::proto("graphene_core::vector::SetFillNode<_, _, _, _, _, _, _>"),
630+
inputs: vec![
631+
DocumentInputType::value("Vector Data", TaggedValue::VectorData(graphene_core::vector::VectorData::empty()), true),
632+
DocumentInputType::value("Fill Type", TaggedValue::FillType(vector::style::FillType::Solid), false),
633+
DocumentInputType::value("Solid Color", TaggedValue::Color(Color::BLACK), false),
634+
DocumentInputType::value("Gradient Type", TaggedValue::GradientType(vector::style::GradientType::Linear), false),
635+
DocumentInputType::value("Start", TaggedValue::DVec2(DVec2::new(0., 0.5)), false),
636+
DocumentInputType::value("End", TaggedValue::DVec2(DVec2::new(1., 0.5)), false),
637+
DocumentInputType::value("Transform", TaggedValue::DAffine2(DAffine2::IDENTITY), false),
638+
DocumentInputType::value("Positions", TaggedValue::GradientPositions(vec![(0., Some(Color::BLACK)), (1., Some(Color::WHITE))]), false),
639+
],
640+
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
641+
properties: node_properties::fill_properties,
642+
},
643+
DocumentNodeType {
644+
name: "Stroke",
636645
category: "Vector",
637-
identifier: NodeImplementation::proto("graphene_std::vector::generator_nodes::BlitSubpath", &[]),
646+
identifier: NodeImplementation::proto("graphene_core::vector::SetStrokeNode<_, _, _, _, _, _, _>"),
638647
inputs: vec![
639-
DocumentInputType::new("Image", TaggedValue::Image(Image::empty()), true),
640-
DocumentInputType::new("Subpath", TaggedValue::Subpath(Subpath::empty()), true),
648+
DocumentInputType::value("Vector Data", TaggedValue::VectorData(graphene_core::vector::VectorData::empty()), true),
649+
DocumentInputType::value("Color", TaggedValue::Color(Color::BLACK), false),
650+
DocumentInputType::value("Weight", TaggedValue::F64(0.), false),
651+
DocumentInputType::value("Dash Lengths", TaggedValue::VecF32(Vec::new()), false),
652+
DocumentInputType::value("Dash Offset", TaggedValue::F64(0.), false),
653+
DocumentInputType::value("Line Cap", TaggedValue::LineCap(graphene_core::vector::style::LineCap::Butt), false),
654+
DocumentInputType::value("Line Join", TaggedValue::LineJoin(graphene_core::vector::style::LineJoin::Miter), false),
655+
DocumentInputType::value("Miter Limit", TaggedValue::F64(4.), false),
641656
],
642-
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Raster)],
643-
properties: node_properties::no_properties,
644-
},*/
657+
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
658+
properties: node_properties::stroke_properties,
659+
},
645660
]
646661
}
647662

@@ -718,14 +733,25 @@ impl DocumentNodeType {
718733
DocumentNodeImplementation::Network(inner_network)
719734
}
720735

736+
/// Converts the [DocumentNodeType] type to a [DocumentNode], based on the inputs from the graph (which must be the correct length) and the metadata
721737
pub fn to_document_node(&self, inputs: impl IntoIterator<Item = NodeInput>, metadata: graph_craft::document::DocumentNodeMetadata) -> DocumentNode {
738+
let inputs: Vec<_> = inputs.into_iter().collect();
739+
assert_eq!(inputs.len(), self.inputs.len(), "Inputs passed from the graph must be equal to the number required");
722740
DocumentNode {
723741
name: self.name.to_string(),
724-
inputs: inputs.into_iter().collect(),
742+
inputs,
725743
implementation: self.generate_implementation(),
726744
metadata,
727745
}
728746
}
747+
748+
/// Converts the [DocumentNodeType] type to a [DocumentNode], using the provided `input_override` and falling back to the default inputs.
749+
/// `input_override` does not have to be the correct length.
750+
pub fn to_document_node_default_inputs(&self, input_override: impl IntoIterator<Item = Option<NodeInput>>, metadata: graph_craft::document::DocumentNodeMetadata) -> DocumentNode {
751+
let mut input_override = input_override.into_iter();
752+
let inputs = self.inputs.iter().map(|default| input_override.next().unwrap_or_default().unwrap_or_else(|| default.default.clone()));
753+
self.to_document_node(inputs, metadata)
754+
}
729755
}
730756

731757
pub fn wrap_network_in_scope(network: NodeNetwork) -> NodeNetwork {
@@ -764,7 +790,7 @@ pub fn new_image_network(output_offset: i32, output_node_id: NodeId) -> NodeNetw
764790
nodes: [
765791
resolve_document_node_type("Input")
766792
.expect("Input node does not exist")
767-
.to_document_node([NodeInput::Network(concrete!(ImageFrame))], DocumentNodeMetadata::position((8, 4))),
793+
.to_document_node_default_inputs([], DocumentNodeMetadata::position((8, 4))),
768794
resolve_document_node_type("Output")
769795
.expect("Output node does not exist")
770796
.to_document_node([NodeInput::node(output_node_id, 0)], DocumentNodeMetadata::position((output_offset + 8, 4))),
@@ -776,3 +802,37 @@ pub fn new_image_network(output_offset: i32, output_node_id: NodeId) -> NodeNetw
776802
..Default::default()
777803
}
778804
}
805+
806+
pub fn new_vector_network(subpath: bezier_rs::Subpath<uuid::ManipulatorGroupId>) -> NodeNetwork {
807+
let input = resolve_document_node_type("Input").expect("Input node does not exist");
808+
let path_generator = resolve_document_node_type("Path Generator").expect("Path Generator node does not exist");
809+
let transform = resolve_document_node_type("Transform").expect("Transform node does not exist");
810+
let fill = resolve_document_node_type("Fill").expect("Fill node does not exist");
811+
let stroke = resolve_document_node_type("Stroke").expect("Stroke node does not exist");
812+
let output = resolve_document_node_type("Output").expect("Output node does not exist");
813+
814+
let mut pos = 0;
815+
let mut next_pos = || {
816+
let node_pos = DocumentNodeMetadata::position((pos, 4));
817+
pos += 8;
818+
node_pos
819+
};
820+
821+
NodeNetwork {
822+
inputs: vec![0],
823+
outputs: vec![NodeOutput::new(5, 0)],
824+
nodes: [
825+
input.to_document_node_default_inputs([], next_pos()),
826+
path_generator.to_document_node_default_inputs([Some(NodeInput::value(TaggedValue::Subpath(subpath), false))], next_pos()),
827+
transform.to_document_node_default_inputs([Some(NodeInput::node(1, 0))], next_pos()),
828+
fill.to_document_node_default_inputs([Some(NodeInput::node(2, 0))], next_pos()),
829+
stroke.to_document_node_default_inputs([Some(NodeInput::node(3, 0))], next_pos()),
830+
output.to_document_node_default_inputs([Some(NodeInput::node(4, 0))], next_pos()),
831+
]
832+
.into_iter()
833+
.enumerate()
834+
.map(|(id, node)| (id as NodeId, node))
835+
.collect(),
836+
..Default::default()
837+
}
838+
}

0 commit comments

Comments
 (0)