Eliminate bare Graphic and Artboard graph data by making Merge and Artboard nodes internally use tables (#2996)
* Eliminate bare Graphic and Artboard graph data by making Merge and Artboard nodes internally use tables * Make the Extend node user-facing
This commit is contained in:
parent
836a110c72
commit
2e1396462c
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -227,25 +227,32 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
node_template: NodeTemplate {
|
node_template: NodeTemplate {
|
||||||
document_node: DocumentNode {
|
document_node: DocumentNode {
|
||||||
implementation: DocumentNodeImplementation::Network(NodeNetwork {
|
implementation: DocumentNodeImplementation::Network(NodeNetwork {
|
||||||
exports: vec![NodeInput::node(NodeId(3), 0)],
|
exports: vec![NodeInput::node(NodeId(4), 0)],
|
||||||
nodes: [
|
nodes: [
|
||||||
// Secondary (left) input type coercion
|
|
||||||
DocumentNode {
|
|
||||||
inputs: vec![NodeInput::network(generic!(T), 1)],
|
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::to_element::IDENTIFIER),
|
|
||||||
manual_composition: Some(concrete!(Context)),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
// Primary (bottom) input type coercion
|
// Primary (bottom) input type coercion
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
inputs: vec![NodeInput::network(generic!(T), 0)],
|
inputs: vec![NodeInput::network(generic!(T), 0)],
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::to_group::IDENTIFIER),
|
implementation: DocumentNodeImplementation::ProtoNode(graphic::to_graphic::IDENTIFIER),
|
||||||
|
manual_composition: Some(concrete!(Context)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
// Secondary (left) input type coercion
|
||||||
|
DocumentNode {
|
||||||
|
inputs: vec![NodeInput::network(generic!(T), 1)],
|
||||||
|
implementation: DocumentNodeImplementation::ProtoNode(graphic::wrap_graphic::IDENTIFIER),
|
||||||
|
manual_composition: Some(concrete!(Context)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
// Store the ID of the parent node (which encapsulates this sub-network) in each row we are extending the table with.
|
||||||
|
DocumentNode {
|
||||||
|
inputs: vec![NodeInput::node(NodeId(1), 0), NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath)],
|
||||||
|
implementation: DocumentNodeImplementation::ProtoNode(graphic::source_node_id::IDENTIFIER),
|
||||||
manual_composition: Some(concrete!(Context)),
|
manual_composition: Some(concrete!(Context)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
// The monitor node is used to display a thumbnail in the UI
|
// The monitor node is used to display a thumbnail in the UI
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
inputs: vec![NodeInput::node(NodeId(2), 0)],
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(memo::monitor::IDENTIFIER),
|
implementation: DocumentNodeImplementation::ProtoNode(memo::monitor::IDENTIFIER),
|
||||||
manual_composition: Some(concrete!(Context)),
|
manual_composition: Some(concrete!(Context)),
|
||||||
skip_deduplication: true,
|
skip_deduplication: true,
|
||||||
|
|
@ -253,12 +260,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
},
|
},
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
manual_composition: Some(generic!(T)),
|
manual_composition: Some(generic!(T)),
|
||||||
inputs: vec![
|
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(3), 0)],
|
||||||
NodeInput::node(NodeId(1), 0),
|
implementation: DocumentNodeImplementation::ProtoNode(graphic::extend::IDENTIFIER),
|
||||||
NodeInput::node(NodeId(2), 0),
|
|
||||||
NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath),
|
|
||||||
],
|
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::layer::IDENTIFIER),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
@ -275,7 +278,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||||
input_metadata: vec![("Graphical Data", "TODO").into(), ("Over", "TODO").into()],
|
input_metadata: vec![("Base", "TODO").into(), ("Content", "TODO").into()],
|
||||||
output_names: vec!["Out".to_string()],
|
output_names: vec!["Out".to_string()],
|
||||||
node_type_metadata: NodeTypePersistentMetadata::layer(IVec2::new(0, 0)),
|
node_type_metadata: NodeTypePersistentMetadata::layer(IVec2::new(0, 0)),
|
||||||
network_metadata: Some(NodeNetworkMetadata {
|
network_metadata: Some(NodeNetworkMetadata {
|
||||||
|
|
@ -283,16 +286,24 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
node_metadata: [
|
node_metadata: [
|
||||||
DocumentNodeMetadata {
|
DocumentNodeMetadata {
|
||||||
persistent_metadata: DocumentNodePersistentMetadata {
|
persistent_metadata: DocumentNodePersistentMetadata {
|
||||||
display_name: "To Element".to_string(),
|
display_name: "To Graphic".to_string(),
|
||||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-14, -1)),
|
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, -3)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
DocumentNodeMetadata {
|
DocumentNodeMetadata {
|
||||||
persistent_metadata: DocumentNodePersistentMetadata {
|
persistent_metadata: DocumentNodePersistentMetadata {
|
||||||
display_name: "To Group".to_string(),
|
display_name: "Wrap Graphic".to_string(),
|
||||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-14, -3)),
|
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, -1)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
DocumentNodeMetadata {
|
||||||
|
persistent_metadata: DocumentNodePersistentMetadata {
|
||||||
|
display_name: "Source Node ID".to_string(),
|
||||||
|
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-14, -1)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -307,7 +318,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
},
|
},
|
||||||
DocumentNodeMetadata {
|
DocumentNodeMetadata {
|
||||||
persistent_metadata: DocumentNodePersistentMetadata {
|
persistent_metadata: DocumentNodePersistentMetadata {
|
||||||
display_name: "Layer".to_string(),
|
display_name: "Extend".to_string(),
|
||||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, -3)),
|
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, -3)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
@ -334,12 +345,12 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
node_template: NodeTemplate {
|
node_template: NodeTemplate {
|
||||||
document_node: DocumentNode {
|
document_node: DocumentNode {
|
||||||
implementation: DocumentNodeImplementation::Network(NodeNetwork {
|
implementation: DocumentNodeImplementation::Network(NodeNetwork {
|
||||||
exports: vec![NodeInput::node(NodeId(2), 0)],
|
exports: vec![NodeInput::node(NodeId(3), 0)],
|
||||||
nodes: [
|
nodes: [
|
||||||
// Ensure this ID is kept in sync with the ID in set_alias so that the name input is kept in sync with the alias
|
// Ensure this ID is kept in sync with the ID in set_alias so that the name input is kept in sync with the alias
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
manual_composition: Some(generic!(T)),
|
manual_composition: Some(generic!(T)),
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(artboard::to_artboard::IDENTIFIER),
|
implementation: DocumentNodeImplementation::ProtoNode(artboard::create_artboard::IDENTIFIER),
|
||||||
inputs: vec![
|
inputs: vec![
|
||||||
NodeInput::network(concrete!(TaggedValue), 1),
|
NodeInput::network(concrete!(TaggedValue), 1),
|
||||||
NodeInput::value(TaggedValue::String(String::from("Artboard")), false),
|
NodeInput::value(TaggedValue::String(String::from("Artboard")), false),
|
||||||
|
|
@ -350,10 +361,17 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
],
|
],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
// Store the ID of the parent node (which encapsulates this sub-network) in each row we are extending the table with.
|
||||||
|
DocumentNode {
|
||||||
|
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath)],
|
||||||
|
implementation: DocumentNodeImplementation::ProtoNode(graphic::source_node_id::IDENTIFIER),
|
||||||
|
manual_composition: Some(concrete!(Context)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
// The monitor node is used to display a thumbnail in the UI.
|
// The monitor node is used to display a thumbnail in the UI.
|
||||||
// TODO: Check if thumbnail is reversed
|
// TODO: Check if thumbnail is reversed
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
inputs: vec![NodeInput::node(NodeId(1), 0)],
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(memo::monitor::IDENTIFIER),
|
implementation: DocumentNodeImplementation::ProtoNode(memo::monitor::IDENTIFIER),
|
||||||
manual_composition: Some(generic!(T)),
|
manual_composition: Some(generic!(T)),
|
||||||
skip_deduplication: true,
|
skip_deduplication: true,
|
||||||
|
|
@ -363,10 +381,10 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
manual_composition: Some(concrete!(Context)),
|
manual_composition: Some(concrete!(Context)),
|
||||||
inputs: vec![
|
inputs: vec![
|
||||||
NodeInput::network(graphene_std::Type::Fn(Box::new(concrete!(Context)), Box::new(concrete!(Table<Artboard>))), 0),
|
NodeInput::network(graphene_std::Type::Fn(Box::new(concrete!(Context)), Box::new(concrete!(Table<Artboard>))), 0),
|
||||||
NodeInput::node(NodeId(1), 0),
|
NodeInput::node(NodeId(2), 0),
|
||||||
NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath),
|
NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath),
|
||||||
],
|
],
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(artboard::append_artboard::IDENTIFIER),
|
implementation: DocumentNodeImplementation::ProtoNode(graphic::extend::IDENTIFIER),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
@ -388,8 +406,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
},
|
},
|
||||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||||
input_metadata: vec![
|
input_metadata: vec![
|
||||||
("Artboards", "TODO").into(),
|
("Base", "TODO").into(),
|
||||||
InputMetadata::with_name_description_override("Contents", "TODO", WidgetOverride::Hidden),
|
InputMetadata::with_name_description_override("Content", "TODO", WidgetOverride::Hidden),
|
||||||
InputMetadata::with_name_description_override(
|
InputMetadata::with_name_description_override(
|
||||||
"Location",
|
"Location",
|
||||||
"TODO",
|
"TODO",
|
||||||
|
|
@ -422,7 +440,15 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
node_metadata: [
|
node_metadata: [
|
||||||
DocumentNodeMetadata {
|
DocumentNodeMetadata {
|
||||||
persistent_metadata: DocumentNodePersistentMetadata {
|
persistent_metadata: DocumentNodePersistentMetadata {
|
||||||
display_name: "To Artboard".to_string(),
|
display_name: "Create Artboard".to_string(),
|
||||||
|
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, -3)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
DocumentNodeMetadata {
|
||||||
|
persistent_metadata: DocumentNodePersistentMetadata {
|
||||||
|
display_name: "Source Node ID".to_string(),
|
||||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-14, -3)),
|
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-14, -3)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
@ -438,7 +464,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||||
},
|
},
|
||||||
DocumentNodeMetadata {
|
DocumentNodeMetadata {
|
||||||
persistent_metadata: DocumentNodePersistentMetadata {
|
persistent_metadata: DocumentNodePersistentMetadata {
|
||||||
display_name: "Append Artboards".to_string(),
|
display_name: "Extend".to_string(),
|
||||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, -4)),
|
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, -4)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -28,30 +28,48 @@ pub struct NodeReplacement<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||||
// graphic element
|
// artboard
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::artboard::append_artboard::IDENTIFIER,
|
node: graphene_std::artboard::create_artboard::IDENTIFIER,
|
||||||
aliases: &["graphene_core::AddArtboardNode", "graphene_core::graphic_element::AppendArtboardNode"],
|
aliases: &[
|
||||||
|
"graphene_core::ConstructArtboardNode",
|
||||||
|
"graphene_core::graphic_element::ToArtboardNode",
|
||||||
|
"graphene_core::artboard::ToArtboardNode",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// graphic
|
||||||
|
NodeReplacement {
|
||||||
|
node: graphene_std::graphic::to_graphic::IDENTIFIER,
|
||||||
|
aliases: &[
|
||||||
|
"graphene_core::ToGraphicGroupNode",
|
||||||
|
"graphene_core::graphic_element::ToGroupNode",
|
||||||
|
"graphene_core::graphic::ToGroupNode",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::artboard::to_artboard::IDENTIFIER,
|
node: graphene_std::graphic::wrap_graphic::IDENTIFIER,
|
||||||
aliases: &["graphene_core::ConstructArtboardNode", "graphene_core::graphic_element::ToArtboardNode"],
|
aliases: &[
|
||||||
|
// Converted from "To Element"
|
||||||
|
"graphene_core::ToGraphicElementNode",
|
||||||
|
"graphene_core::graphic_element::ToElementNode",
|
||||||
|
"graphene_core::graphic::ToElementNode",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::graphic::to_element::IDENTIFIER,
|
node: graphene_std::graphic::legacy_layer_extend::IDENTIFIER,
|
||||||
aliases: &["graphene_core::ToGraphicElementNode", "graphene_core::graphic_element::ToElementNode"],
|
aliases: &[
|
||||||
|
"graphene_core::graphic_element::LayerNode",
|
||||||
|
"graphene_core::graphic::LayerNode",
|
||||||
|
// Converted from "Append Artboard"
|
||||||
|
"graphene_core::AddArtboardNode",
|
||||||
|
"graphene_core::graphic_element::AppendArtboardNode",
|
||||||
|
"graphene_core::graphic::AppendArtboardNode",
|
||||||
|
"graphene_core::artboard::AppendArtboardNode",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::graphic::to_group::IDENTIFIER,
|
node: graphene_std::graphic::flatten_graphic::IDENTIFIER,
|
||||||
aliases: &["graphene_core::ToGraphicGroupNode", "graphene_core::graphic_element::ToGroupNode"],
|
aliases: &["graphene_core::graphic_element::FlattenGroupNode", "graphene_core::graphic::FlattenGroupNode"],
|
||||||
},
|
|
||||||
NodeReplacement {
|
|
||||||
node: graphene_std::graphic::layer::IDENTIFIER,
|
|
||||||
aliases: &["graphene_core::graphic_element::LayerNode"],
|
|
||||||
},
|
|
||||||
NodeReplacement {
|
|
||||||
node: graphene_std::graphic::flatten_group::IDENTIFIER,
|
|
||||||
aliases: &["graphene_core::graphic_element::FlattenGroupNode"],
|
|
||||||
},
|
},
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::graphic::flatten_vector::IDENTIFIER,
|
node: graphene_std::graphic::flatten_vector::IDENTIFIER,
|
||||||
|
|
@ -245,8 +263,8 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||||
aliases: &["graphene_core::ops::SomeNode"],
|
aliases: &["graphene_core::ops::SomeNode"],
|
||||||
},
|
},
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::debug::unwrap::IDENTIFIER,
|
node: graphene_std::debug::unwrap_option::IDENTIFIER,
|
||||||
aliases: &["graphene_core::ops::UnwrapNode"],
|
aliases: &["graphene_core::ops::UnwrapNode", "graphene_core::debug::UnwrapNode"],
|
||||||
},
|
},
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::debug::clone::IDENTIFIER,
|
node: graphene_std::debug::clone::IDENTIFIER,
|
||||||
|
|
@ -812,7 +830,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
||||||
document.network_interface.set_input(&InputConnector::node(*node_id, 4), old_inputs[3].clone(), network_path);
|
document.network_interface.set_input(&InputConnector::node(*node_id, 4), old_inputs[3].clone(), network_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upgrade artboard name being passed as hidden value input to "To Artboard"
|
// Upgrade artboard name being passed as hidden value input to "Create Artboard"
|
||||||
if reference == "Artboard" && reset_node_definitions_on_open {
|
if reference == "Artboard" && reset_node_definitions_on_open {
|
||||||
let label = document.network_interface.display_name(node_id, network_path);
|
let label = document.network_interface.display_name(node_id, network_path);
|
||||||
document
|
document
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,13 @@ impl TableRowLayout for Vector {
|
||||||
"Vector"
|
"Vector"
|
||||||
}
|
}
|
||||||
fn identifier(&self) -> String {
|
fn identifier(&self) -> String {
|
||||||
format!("Vector ({} points, {} segments)", self.point_domain.ids().len(), self.segment_domain.ids().len())
|
format!(
|
||||||
|
"Vector ({} point{}, {} segment{})",
|
||||||
|
self.point_domain.ids().len(),
|
||||||
|
if self.point_domain.ids().len() == 1 { "" } else { "s" },
|
||||||
|
self.segment_domain.ids().len(),
|
||||||
|
if self.segment_domain.ids().len() == 1 { "" } else { "s" }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
||||||
let colinear = self.colinear_manipulators.iter().map(|[a, b]| format!("[{a} / {b}]")).collect::<Vec<_>>().join(", ");
|
let colinear = self.colinear_manipulators.iter().map(|[a, b]| format!("[{a} / {b}]")).collect::<Vec<_>>().join(", ");
|
||||||
|
|
@ -247,10 +253,10 @@ impl TableRowLayout for Image<Color> {
|
||||||
"Image"
|
"Image"
|
||||||
}
|
}
|
||||||
fn identifier(&self) -> String {
|
fn identifier(&self) -> String {
|
||||||
format!("Image (width={}, height={})", self.width, self.height)
|
format!("Image ({}x{})", self.width, self.height)
|
||||||
}
|
}
|
||||||
fn compute_layout(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
fn compute_layout(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
|
||||||
let rows = vec![vec![TextLabel::new(format!("Image (width={}, height={})", self.width, self.height)).widget_holder()]];
|
let rows = vec![vec![TextLabel::new(format!("Image ({}x{})", self.width, self.height)).widget_holder()]];
|
||||||
vec![LayoutGroup::Table { rows }]
|
vec![LayoutGroup::Table { rows }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -272,7 +278,7 @@ impl<T: TableRowLayout> TableRowLayout for Table<T> {
|
||||||
"Table"
|
"Table"
|
||||||
}
|
}
|
||||||
fn identifier(&self) -> String {
|
fn identifier(&self) -> String {
|
||||||
format!("Table<{}> (length={})", T::type_name(), self.len())
|
format!("Table<{}> ({} row{})", T::type_name(), self.len(), if self.len() == 1 { "" } else { "s" })
|
||||||
}
|
}
|
||||||
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
fn compute_layout(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
||||||
if let Some(index) = data.desired_path.get(data.current_depth).copied() {
|
if let Some(index) = data.desired_path.get(data.current_depth).copied() {
|
||||||
|
|
@ -295,7 +301,7 @@ impl<T: TableRowLayout> TableRowLayout for Table<T> {
|
||||||
let rotation = if angle == -0. { 0. } else { angle.to_degrees() };
|
let rotation = if angle == -0. { 0. } else { angle.to_degrees() };
|
||||||
let round = |x: f64| (x * 1e3).round() / 1e3;
|
let round = |x: f64| (x * 1e3).round() / 1e3;
|
||||||
vec![
|
vec![
|
||||||
TextLabel::new(format!("{}", index)).widget_holder(),
|
TextLabel::new(format!("{index}")).widget_holder(),
|
||||||
TextButton::new(row.element.identifier())
|
TextButton::new(row.element.identifier())
|
||||||
.on_update(move |_| SpreadsheetMessage::PushToElementPath { index }.into())
|
.on_update(move |_| SpreadsheetMessage::PushToElementPath { index }.into())
|
||||||
.widget_holder(),
|
.widget_holder(),
|
||||||
|
|
@ -315,7 +321,6 @@ impl<T: TableRowLayout> TableRowLayout for Table<T> {
|
||||||
|
|
||||||
rows.insert(0, column_headings(&["", "element", "transform", "alpha_blending", "source_node_id"]));
|
rows.insert(0, column_headings(&["", "element", "transform", "alpha_blending", "source_node_id"]));
|
||||||
|
|
||||||
let table = vec![TextLabel::new("Table:").widget_holder()];
|
vec![LayoutGroup::Table { rows }]
|
||||||
vec![LayoutGroup::Row { widgets: table }, LayoutGroup::Table { rows }]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -564,13 +564,17 @@ impl Fsm for ArtboardToolFsmState {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_artboard {
|
mod test_artboard {
|
||||||
pub use crate::test_utils::test_prelude::*;
|
pub use crate::test_utils::test_prelude::*;
|
||||||
|
use graphene_std::table::Table;
|
||||||
|
|
||||||
async fn get_artboards(editor: &mut EditorTestUtils) -> Vec<graphene_std::Artboard> {
|
async fn get_artboards(editor: &mut EditorTestUtils) -> Table<graphene_std::Artboard> {
|
||||||
let instrumented = match editor.eval_graph().await {
|
let instrumented = match editor.eval_graph().await {
|
||||||
Ok(instrumented) => instrumented,
|
Ok(instrumented) => instrumented,
|
||||||
Err(e) => panic!("Failed to evaluate graph: {}", e),
|
Err(e) => panic!("Failed to evaluate graph: {}", e),
|
||||||
};
|
};
|
||||||
instrumented.grab_all_input::<graphene_std::artboard::append_artboard::ArtboardInput>(&editor.runtime).collect()
|
instrumented
|
||||||
|
.grab_all_input::<graphene_std::graphic::extend::NewInput<graphene_std::Artboard>>(&editor.runtime)
|
||||||
|
.flatten()
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -582,8 +586,8 @@ mod test_artboard {
|
||||||
let artboards = get_artboards(&mut editor).await;
|
let artboards = get_artboards(&mut editor).await;
|
||||||
|
|
||||||
assert_eq!(artboards.len(), 1);
|
assert_eq!(artboards.len(), 1);
|
||||||
assert_eq!(artboards[0].location, IVec2::new(10, 0));
|
assert_eq!(artboards.get(0).unwrap().element.location, IVec2::new(10, 0));
|
||||||
assert_eq!(artboards[0].dimensions, IVec2::new(10, 11));
|
assert_eq!(artboards.get(0).unwrap().element.dimensions, IVec2::new(10, 11));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -594,8 +598,8 @@ mod test_artboard {
|
||||||
|
|
||||||
let artboards = get_artboards(&mut editor).await;
|
let artboards = get_artboards(&mut editor).await;
|
||||||
assert_eq!(artboards.len(), 1);
|
assert_eq!(artboards.len(), 1);
|
||||||
assert_eq!(artboards[0].location, IVec2::new(-10, 10));
|
assert_eq!(artboards.get(0).unwrap().element.location, IVec2::new(-10, 10));
|
||||||
assert_eq!(artboards[0].dimensions, IVec2::new(20, 20));
|
assert_eq!(artboards.get(0).unwrap().element.dimensions, IVec2::new(20, 20));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -613,9 +617,9 @@ mod test_artboard {
|
||||||
|
|
||||||
let artboards = get_artboards(&mut editor).await;
|
let artboards = get_artboards(&mut editor).await;
|
||||||
assert_eq!(artboards.len(), 1);
|
assert_eq!(artboards.len(), 1);
|
||||||
assert_eq!(artboards[0].location, IVec2::new(0, 0));
|
assert_eq!(artboards.get(0).unwrap().element.location, IVec2::new(0, 0));
|
||||||
let desired_size = DVec2::splat(f64::consts::FRAC_1_SQRT_2 * 10.);
|
let desired_size = DVec2::splat(f64::consts::FRAC_1_SQRT_2 * 10.);
|
||||||
assert_eq!(artboards[0].dimensions, desired_size.round().as_ivec2());
|
assert_eq!(artboards.get(0).unwrap().element.dimensions, desired_size.round().as_ivec2());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -634,9 +638,9 @@ mod test_artboard {
|
||||||
|
|
||||||
let artboards = get_artboards(&mut editor).await;
|
let artboards = get_artboards(&mut editor).await;
|
||||||
assert_eq!(artboards.len(), 1);
|
assert_eq!(artboards.len(), 1);
|
||||||
assert_eq!(artboards[0].location, DVec2::splat(f64::consts::FRAC_1_SQRT_2 * -10.).as_ivec2());
|
assert_eq!(artboards.get(0).unwrap().element.location, DVec2::splat(f64::consts::FRAC_1_SQRT_2 * -10.).as_ivec2());
|
||||||
let desired_size = DVec2::splat(f64::consts::FRAC_1_SQRT_2 * 20.);
|
let desired_size = DVec2::splat(f64::consts::FRAC_1_SQRT_2 * 20.);
|
||||||
assert_eq!(artboards[0].dimensions, desired_size.round().as_ivec2());
|
assert_eq!(artboards.get(0).unwrap().element.dimensions, desired_size.round().as_ivec2());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ use graph_craft::graphene_compiler::Compiler;
|
||||||
use graph_craft::proto::GraphErrors;
|
use graph_craft::proto::GraphErrors;
|
||||||
use graph_craft::wasm_application_io::EditorPreferences;
|
use graph_craft::wasm_application_io::EditorPreferences;
|
||||||
use graph_craft::{ProtoNodeIdentifier, concrete};
|
use graph_craft::{ProtoNodeIdentifier, concrete};
|
||||||
use graphene_std::Context;
|
|
||||||
use graphene_std::application_io::{ImageTexture, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
|
use graphene_std::application_io::{ImageTexture, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
|
||||||
use graphene_std::memo::IORecord;
|
use graphene_std::memo::IORecord;
|
||||||
use graphene_std::renderer::{Render, RenderParams, SvgRender};
|
use graphene_std::renderer::{Render, RenderParams, SvgRender};
|
||||||
|
|
@ -17,6 +16,7 @@ use graphene_std::text::FontCache;
|
||||||
use graphene_std::vector::Vector;
|
use graphene_std::vector::Vector;
|
||||||
use graphene_std::vector::style::ViewMode;
|
use graphene_std::vector::style::ViewMode;
|
||||||
use graphene_std::wasm_application_io::{RenderOutputType, WasmApplicationIo, WasmEditorApi};
|
use graphene_std::wasm_application_io::{RenderOutputType, WasmApplicationIo, WasmEditorApi};
|
||||||
|
use graphene_std::{Artboard, Context, Graphic};
|
||||||
use interpreted_executor::dynamic_executor::{DynamicExecutor, IntrospectError, ResolvedDocumentNodeTypesDelta};
|
use interpreted_executor::dynamic_executor::{DynamicExecutor, IntrospectError, ResolvedDocumentNodeTypesDelta};
|
||||||
use interpreted_executor::util::wrap_network_in_scope;
|
use interpreted_executor::util::wrap_network_in_scope;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
@ -308,9 +308,9 @@ impl NodeRuntime {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, graphene_std::Graphic>>() {
|
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<Graphic>>>() {
|
||||||
Self::process_graphic(&mut self.thumbnail_renders, parent_network_node_id, &io.output, responses, update_thumbnails)
|
Self::process_graphic(&mut self.thumbnail_renders, parent_network_node_id, &io.output, responses, update_thumbnails)
|
||||||
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, graphene_std::Artboard>>() {
|
} else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<Artboard>>>() {
|
||||||
Self::process_graphic(&mut self.thumbnail_renders, parent_network_node_id, &io.output, responses, update_thumbnails)
|
Self::process_graphic(&mut self.thumbnail_renders, parent_network_node_id, &io.output, responses, update_thumbnails)
|
||||||
// Insert the vector modify if we are dealing with vector data
|
// Insert the vector modify if we are dealing with vector data
|
||||||
} else if let Some(record) = introspected_data.downcast_ref::<IORecord<Context, Table<Vector>>>() {
|
} else if let Some(record) = introspected_data.downcast_ref::<IORecord<Context, Table<Vector>>>() {
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@
|
||||||
|
|
||||||
<style lang="scss" global>
|
<style lang="scss" global>
|
||||||
.node-catalog {
|
.node-catalog {
|
||||||
max-height: 40vh;
|
max-height: 30vh;
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ impl BoundingBox for Table<Artboard> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node(category(""))]
|
#[node_macro::node(category(""))]
|
||||||
async fn to_artboard<Data: Into<Table<Graphic>> + 'n>(
|
async fn create_artboard<T: Into<Table<Graphic>> + 'n>(
|
||||||
ctx: impl ExtractAll + CloneVarArgs + Ctx,
|
ctx: impl ExtractAll + CloneVarArgs + Ctx,
|
||||||
#[implementations(
|
#[implementations(
|
||||||
Context -> Table<Graphic>,
|
Context -> Table<Graphic>,
|
||||||
|
|
@ -104,13 +104,13 @@ async fn to_artboard<Data: Into<Table<Graphic>> + 'n>(
|
||||||
Context -> Table<Raster<GPU>>,
|
Context -> Table<Raster<GPU>>,
|
||||||
Context -> DAffine2,
|
Context -> DAffine2,
|
||||||
)]
|
)]
|
||||||
contents: impl Node<Context<'static>, Output = Data>,
|
content: impl Node<Context<'static>, Output = T>,
|
||||||
label: String,
|
label: String,
|
||||||
location: DVec2,
|
location: DVec2,
|
||||||
dimensions: DVec2,
|
dimensions: DVec2,
|
||||||
background: Color,
|
background: Color,
|
||||||
clip: bool,
|
clip: bool,
|
||||||
) -> Artboard {
|
) -> Table<Artboard> {
|
||||||
let location = location.as_ivec2();
|
let location = location.as_ivec2();
|
||||||
|
|
||||||
let footprint = ctx.try_footprint().copied();
|
let footprint = ctx.try_footprint().copied();
|
||||||
|
|
@ -119,7 +119,7 @@ async fn to_artboard<Data: Into<Table<Graphic>> + 'n>(
|
||||||
footprint.translate(location.as_dvec2());
|
footprint.translate(location.as_dvec2());
|
||||||
new_ctx = new_ctx.with_footprint(footprint);
|
new_ctx = new_ctx.with_footprint(footprint);
|
||||||
}
|
}
|
||||||
let group = contents.eval(new_ctx.into_context()).await.into();
|
let group = content.eval(new_ctx.into_context()).await.into();
|
||||||
|
|
||||||
let dimensions = dimensions.as_ivec2().max(IVec2::ONE);
|
let dimensions = dimensions.as_ivec2().max(IVec2::ONE);
|
||||||
|
|
||||||
|
|
@ -127,28 +127,12 @@ async fn to_artboard<Data: Into<Table<Graphic>> + 'n>(
|
||||||
|
|
||||||
let dimensions = dimensions.abs();
|
let dimensions = dimensions.abs();
|
||||||
|
|
||||||
Artboard {
|
Table::new_from_element(Artboard {
|
||||||
group,
|
group,
|
||||||
label,
|
label,
|
||||||
location,
|
location,
|
||||||
dimensions,
|
dimensions,
|
||||||
background,
|
background,
|
||||||
clip,
|
clip,
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
#[node_macro::node(category(""))]
|
|
||||||
pub async fn append_artboard(_ctx: impl Ctx, mut artboards: Table<Artboard>, artboard: Artboard, node_path: Vec<NodeId>) -> Table<Artboard> {
|
|
||||||
// Get the penultimate element of the node path, or None if the path is too short.
|
|
||||||
// This is used to get the ID of the user-facing "Artboard" node (which encapsulates this internal "Append Artboard" node).
|
|
||||||
let encapsulating_node_id = node_path.get(node_path.len().wrapping_sub(2)).copied();
|
|
||||||
|
|
||||||
artboards.push(TableRow {
|
|
||||||
element: artboard,
|
|
||||||
transform: DAffine2::IDENTITY,
|
|
||||||
alpha_blending: AlphaBlending::default(),
|
|
||||||
source_node_id: encapsulating_node_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
artboards
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use glam::{DAffine2, DVec2};
|
||||||
#[node_macro::node(category("Debug"), name("Log to Console"))]
|
#[node_macro::node(category("Debug"), name("Log to Console"))]
|
||||||
fn log_to_console<T: std::fmt::Debug>(_: impl Ctx, #[implementations(String, bool, f64, u32, u64, DVec2, Table<Vector>, DAffine2, Color, Option<Color>)] value: T) -> T {
|
fn log_to_console<T: std::fmt::Debug>(_: impl Ctx, #[implementations(String, bool, f64, u32, u64, DVec2, Table<Vector>, DAffine2, Color, Option<Color>)] value: T) -> T {
|
||||||
// KEEP THIS `debug!()` - It acts as the output for the debug node itself
|
// KEEP THIS `debug!()` - It acts as the output for the debug node itself
|
||||||
log::debug!("{:#?}", value);
|
log::debug!("{value:#?}");
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ fn some<T>(_: impl Ctx, #[implementations(f64, f32, u32, u64, String, Color)] in
|
||||||
|
|
||||||
/// Meant for debugging purposes, not general use. Unwraps the input value from an Option, returning the default value if the input is None.
|
/// Meant for debugging purposes, not general use. Unwraps the input value from an Option, returning the default value if the input is None.
|
||||||
#[node_macro::node(category("Debug"))]
|
#[node_macro::node(category("Debug"))]
|
||||||
fn unwrap<T: Default>(_: impl Ctx, #[implementations(Option<f64>, Option<f32>, Option<u32>, Option<u64>, Option<String>, Option<Color>)] input: Option<T>) -> T {
|
fn unwrap_option<T: Default>(_: impl Ctx, #[implementations(Option<f64>, Option<u32>, Option<u64>, Option<String>, Option<Color>)] input: Option<T>) -> T {
|
||||||
input.unwrap_or_default()
|
input.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use crate::raster_types::{CPU, GPU, Raster};
|
||||||
use crate::table::{Table, TableRow};
|
use crate::table::{Table, TableRow};
|
||||||
use crate::uuid::NodeId;
|
use crate::uuid::NodeId;
|
||||||
use crate::vector::Vector;
|
use crate::vector::Vector;
|
||||||
use crate::{Color, Ctx};
|
use crate::{Artboard, Color, Ctx};
|
||||||
use dyn_any::DynAny;
|
use dyn_any::DynAny;
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
@ -194,27 +194,66 @@ impl BoundingBox for Table<Graphic> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node(category(""))]
|
#[node_macro::node(category(""))]
|
||||||
async fn layer<I: 'n + Send + Clone>(
|
async fn source_node_id<I: 'n + Send + Clone>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
#[implementations(Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>)] mut stack: Table<I>,
|
#[implementations(Table<Artboard>, Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>)] content: Table<I>,
|
||||||
#[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>)] element: I,
|
|
||||||
node_path: Vec<NodeId>,
|
node_path: Vec<NodeId>,
|
||||||
) -> Table<I> {
|
) -> Table<I> {
|
||||||
// Get the penultimate element of the node path, or None if the path is too short
|
// Get the penultimate element of the node path, or None if the path is too short
|
||||||
|
// This is used to get the ID of the user-facing parent layer-style node (which encapsulates this internal node).
|
||||||
let source_node_id = node_path.get(node_path.len().wrapping_sub(2)).copied();
|
let source_node_id = node_path.get(node_path.len().wrapping_sub(2)).copied();
|
||||||
|
|
||||||
stack.push(TableRow {
|
let mut content = content;
|
||||||
element,
|
for row in content.iter_mut() {
|
||||||
transform: DAffine2::IDENTITY,
|
*row.source_node_id = source_node_id;
|
||||||
alpha_blending: AlphaBlending::default(),
|
}
|
||||||
source_node_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
stack
|
content
|
||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("Debug"))]
|
/// Joins two tables of the same type, extending the base table with the rows of the new table.
|
||||||
async fn to_element<Data: Into<Graphic> + 'n>(
|
#[node_macro::node(category("General"))]
|
||||||
|
async fn extend<I: 'n + Send + Clone>(
|
||||||
|
_: impl Ctx,
|
||||||
|
/// The table whose rows will appear at the start of the extended table.
|
||||||
|
#[implementations(Table<Artboard>, Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>)]
|
||||||
|
base: Table<I>,
|
||||||
|
/// The table whose rows will appear at the end of the extended table.
|
||||||
|
#[expose]
|
||||||
|
#[implementations(Table<Artboard>, Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>)]
|
||||||
|
new: Table<I>,
|
||||||
|
) -> Table<I> {
|
||||||
|
let mut base = base;
|
||||||
|
base.extend(new);
|
||||||
|
|
||||||
|
base
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Eventually remove this document upgrade code
|
||||||
|
#[node_macro::node(category(""))]
|
||||||
|
async fn legacy_layer_extend<I: 'n + Send + Clone>(
|
||||||
|
_: impl Ctx,
|
||||||
|
#[implementations(Table<Artboard>, Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>)] base: Table<I>,
|
||||||
|
#[expose]
|
||||||
|
#[implementations(Table<Artboard>, Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>)]
|
||||||
|
new: Table<I>,
|
||||||
|
nested_node_path: Vec<NodeId>,
|
||||||
|
) -> Table<I> {
|
||||||
|
// Get the penultimate element of the node path, or None if the path is too short
|
||||||
|
// This is used to get the ID of the user-facing parent layer-style node (which encapsulates this internal node).
|
||||||
|
let source_node_id = nested_node_path.get(nested_node_path.len().wrapping_sub(2)).copied();
|
||||||
|
|
||||||
|
let mut base = base;
|
||||||
|
for row in new.into_iter() {
|
||||||
|
base.push(TableRow { source_node_id, ..row });
|
||||||
|
}
|
||||||
|
|
||||||
|
base
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Places a table of graphical content into an element of a new wrapper graphic table.
|
||||||
|
#[node_macro::node(category("General"))]
|
||||||
|
async fn wrap_graphic<T: Into<Graphic> + 'n>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
#[implementations(
|
#[implementations(
|
||||||
Table<Graphic>,
|
Table<Graphic>,
|
||||||
|
|
@ -223,13 +262,15 @@ async fn to_element<Data: Into<Graphic> + 'n>(
|
||||||
Table<Raster<GPU>>,
|
Table<Raster<GPU>>,
|
||||||
DAffine2,
|
DAffine2,
|
||||||
)]
|
)]
|
||||||
data: Data,
|
content: T,
|
||||||
) -> Graphic {
|
) -> Table<Graphic> {
|
||||||
data.into()
|
Table::new_from_element(content.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("General"))]
|
/// Converts a table of graphical content into a graphic table by placing it into an element of a new wrapper graphic table.
|
||||||
async fn to_group<Data: Into<Table<Graphic>> + 'n>(
|
/// If it is already a graphic table, it is not wrapped again. Use the 'Wrap Graphic' node if wrapping is always desired.
|
||||||
|
#[node_macro::node(category("Type Conversion"))]
|
||||||
|
async fn to_graphic<T: Into<Table<Graphic>> + 'n>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
#[implementations(
|
#[implementations(
|
||||||
Table<Graphic>,
|
Table<Graphic>,
|
||||||
|
|
@ -237,34 +278,34 @@ async fn to_group<Data: Into<Table<Graphic>> + 'n>(
|
||||||
Table<Raster<CPU>>,
|
Table<Raster<CPU>>,
|
||||||
Table<Raster<GPU>>,
|
Table<Raster<GPU>>,
|
||||||
)]
|
)]
|
||||||
element: Data,
|
content: T,
|
||||||
) -> Table<Graphic> {
|
) -> Table<Graphic> {
|
||||||
element.into()
|
content.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("General"))]
|
#[node_macro::node(category("General"))]
|
||||||
async fn flatten_group(_: impl Ctx, group: Table<Graphic>, fully_flatten: bool) -> Table<Graphic> {
|
async fn flatten_graphic(_: impl Ctx, content: Table<Graphic>, fully_flatten: bool) -> Table<Graphic> {
|
||||||
// TODO: Avoid mutable reference, instead return a new Table<Graphic>?
|
// TODO: Avoid mutable reference, instead return a new Table<Graphic>?
|
||||||
fn flatten_group(output_group_table: &mut Table<Graphic>, current_group_table: Table<Graphic>, fully_flatten: bool, recursion_depth: usize) {
|
fn flatten_table(output_graphic_table: &mut Table<Graphic>, current_graphic_table: Table<Graphic>, fully_flatten: bool, recursion_depth: usize) {
|
||||||
for current_row in current_group_table.iter() {
|
for current_row in current_graphic_table.iter() {
|
||||||
let current_element = current_row.element.clone();
|
let current_element = current_row.element.clone();
|
||||||
let reference = *current_row.source_node_id;
|
let reference = *current_row.source_node_id;
|
||||||
|
|
||||||
let recurse = fully_flatten || recursion_depth == 0;
|
let recurse = fully_flatten || recursion_depth == 0;
|
||||||
|
|
||||||
match current_element {
|
match current_element {
|
||||||
// If we're allowed to recurse, flatten any groups we encounter
|
// If we're allowed to recurse, flatten any graphics we encounter
|
||||||
Graphic::Group(mut current_element) if recurse => {
|
Graphic::Group(mut current_element) if recurse => {
|
||||||
// Apply the parent group's transform to all child elements
|
// Apply the parent graphic's transform to all child elements
|
||||||
for graphic in current_element.iter_mut() {
|
for graphic in current_element.iter_mut() {
|
||||||
*graphic.transform = *current_row.transform * *graphic.transform;
|
*graphic.transform = *current_row.transform * *graphic.transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
flatten_group(output_group_table, current_element, fully_flatten, recursion_depth + 1);
|
flatten_table(output_graphic_table, current_element, fully_flatten, recursion_depth + 1);
|
||||||
}
|
}
|
||||||
// Handle any leaf elements we encounter, which can be either non-group elements or groups that we don't want to flatten
|
// Push any leaf Graphic elements we encounter, which can be either Graphic table elements beyond the recursion depth, or table elements other than Graphic tables
|
||||||
_ => {
|
_ => {
|
||||||
output_group_table.push(TableRow {
|
output_graphic_table.push(TableRow {
|
||||||
element: current_element,
|
element: current_element,
|
||||||
transform: *current_row.transform,
|
transform: *current_row.transform,
|
||||||
alpha_blending: *current_row.alpha_blending,
|
alpha_blending: *current_row.alpha_blending,
|
||||||
|
|
@ -276,33 +317,33 @@ async fn flatten_group(_: impl Ctx, group: Table<Graphic>, fully_flatten: bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output = Table::new();
|
let mut output = Table::new();
|
||||||
flatten_group(&mut output, group, fully_flatten, 0);
|
flatten_table(&mut output, content, fully_flatten, 0);
|
||||||
|
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("Vector"))]
|
#[node_macro::node(category("Vector"))]
|
||||||
async fn flatten_vector(_: impl Ctx, group: Table<Graphic>) -> Table<Vector> {
|
async fn flatten_vector(_: impl Ctx, content: Table<Graphic>) -> Table<Vector> {
|
||||||
// TODO: Avoid mutable reference, instead return a new Table<Graphic>?
|
// TODO: Avoid mutable reference, instead return a new Table<Graphic>?
|
||||||
fn flatten_group(output_group_table: &mut Table<Vector>, current_group_table: Table<Graphic>) {
|
fn flatten_table(output_vector_table: &mut Table<Vector>, current_graphic_table: Table<Graphic>) {
|
||||||
for current_graphic_row in current_group_table.iter() {
|
for current_graphic_row in current_graphic_table.iter() {
|
||||||
let current_graphic = current_graphic_row.element.clone();
|
let current_graphic = current_graphic_row.element.clone();
|
||||||
let source_node_id = *current_graphic_row.source_node_id;
|
let source_node_id = *current_graphic_row.source_node_id;
|
||||||
|
|
||||||
match current_graphic {
|
match current_graphic {
|
||||||
// If we're allowed to recurse, flatten any groups we encounter
|
// If we're allowed to recurse, flatten any tables we encounter
|
||||||
Graphic::Group(mut current_graphic_table) => {
|
Graphic::Group(mut current_graphic_table) => {
|
||||||
// Apply the parent group's transform to all child elements
|
// Apply the parent graphic's transform to all child elements
|
||||||
for graphic in current_graphic_table.iter_mut() {
|
for graphic in current_graphic_table.iter_mut() {
|
||||||
*graphic.transform = *current_graphic_row.transform * *graphic.transform;
|
*graphic.transform = *current_graphic_row.transform * *graphic.transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
flatten_group(output_group_table, current_graphic_table);
|
flatten_table(output_vector_table, current_graphic_table);
|
||||||
}
|
}
|
||||||
// Handle any leaf elements we encounter, which can be either non-group elements or groups that we don't want to flatten
|
// Push any leaf Vector elements we encounter
|
||||||
Graphic::Vector(vector_table) => {
|
Graphic::Vector(vector_table) => {
|
||||||
for current_vector_row in vector_table.iter() {
|
for current_vector_row in vector_table.iter() {
|
||||||
output_group_table.push(TableRow {
|
output_vector_table.push(TableRow {
|
||||||
element: current_vector_row.element.clone(),
|
element: current_vector_row.element.clone(),
|
||||||
transform: *current_graphic_row.transform * *current_vector_row.transform,
|
transform: *current_graphic_row.transform * *current_vector_row.transform,
|
||||||
alpha_blending: AlphaBlending {
|
alpha_blending: AlphaBlending {
|
||||||
|
|
@ -321,7 +362,7 @@ async fn flatten_vector(_: impl Ctx, group: Table<Graphic>) -> Table<Vector> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output = Table::new();
|
let mut output = Table::new();
|
||||||
flatten_group(&mut output, group);
|
flatten_table(&mut output, content);
|
||||||
|
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use crate::vector::Vector;
|
||||||
use crate::{Context, Ctx};
|
use crate::{Context, Ctx};
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
|
|
||||||
#[node_macro::node(category("Text"))]
|
#[node_macro::node(category("Type Conversion"))]
|
||||||
fn to_string<T: std::fmt::Debug>(_: impl Ctx, #[implementations(String, bool, f64, u32, u64, DVec2, DAffine2, Table<Vector>)] value: T) -> String {
|
fn to_string<T: std::fmt::Debug>(_: impl Ctx, #[implementations(String, bool, f64, u32, u64, DVec2, DAffine2, Table<Vector>)] value: T) -> String {
|
||||||
format!("{:?}", value)
|
format!("{:?}", value)
|
||||||
}
|
}
|
||||||
|
|
@ -60,11 +60,10 @@ async fn switch<T, C: Send + 'n + Clone>(
|
||||||
Context -> DVec2,
|
Context -> DVec2,
|
||||||
Context -> DAffine2,
|
Context -> DAffine2,
|
||||||
Context -> Table<Artboard>,
|
Context -> Table<Artboard>,
|
||||||
Context -> Table<Vector>,
|
|
||||||
Context -> Table<Graphic>,
|
Context -> Table<Graphic>,
|
||||||
|
Context -> Table<Vector>,
|
||||||
Context -> Table<Raster<CPU>>,
|
Context -> Table<Raster<CPU>>,
|
||||||
Context -> Table<Raster<GPU>>,
|
Context -> Table<Raster<GPU>>,
|
||||||
Context -> Graphic,
|
|
||||||
Context -> Color,
|
Context -> Color,
|
||||||
Context -> Option<Color>,
|
Context -> Option<Color>,
|
||||||
Context -> GradientStops,
|
Context -> GradientStops,
|
||||||
|
|
@ -81,11 +80,10 @@ async fn switch<T, C: Send + 'n + Clone>(
|
||||||
Context -> DVec2,
|
Context -> DVec2,
|
||||||
Context -> DAffine2,
|
Context -> DAffine2,
|
||||||
Context -> Table<Artboard>,
|
Context -> Table<Artboard>,
|
||||||
Context -> Table<Vector>,
|
|
||||||
Context -> Table<Graphic>,
|
Context -> Table<Graphic>,
|
||||||
|
Context -> Table<Vector>,
|
||||||
Context -> Table<Raster<CPU>>,
|
Context -> Table<Raster<CPU>>,
|
||||||
Context -> Table<Raster<GPU>>,
|
Context -> Table<Raster<GPU>>,
|
||||||
Context -> Graphic,
|
|
||||||
Context -> Color,
|
Context -> Color,
|
||||||
Context -> Option<Color>,
|
Context -> Option<Color>,
|
||||||
Context -> GradientStops,
|
Context -> GradientStops,
|
||||||
|
|
|
||||||
|
|
@ -965,8 +965,8 @@ where
|
||||||
// connected to a Flatten Path connected to an if else node, another connection from the cache directly to
|
// connected to a Flatten Path connected to an if else node, another connection from the cache directly to
|
||||||
// the if else node, and another connection from the cache to a matches type node connected to the if else node.
|
// the if else node, and another connection from the cache to a matches type node connected to the if else node.
|
||||||
|
|
||||||
fn flatten_group(group: &Table<Graphic>, output: &mut TableRowMut<Vector>) {
|
fn flatten_table(output: &mut TableRowMut<Vector>, graphic_table: &Table<Graphic>) {
|
||||||
for (group_index, current_element) in group.iter().enumerate() {
|
for (current_index, current_element) in graphic_table.iter().enumerate() {
|
||||||
match current_element.element {
|
match current_element.element {
|
||||||
Graphic::Vector(vector) => {
|
Graphic::Vector(vector) => {
|
||||||
// Loop through every row of the `Table<Vector>` and concatenate each element's subpath into the output `Vector` element.
|
// Loop through every row of the `Table<Vector>` and concatenate each element's subpath into the output `Vector` element.
|
||||||
|
|
@ -976,7 +976,7 @@ where
|
||||||
let node_id = current_element.source_node_id.map(|node_id| node_id.0).unwrap_or_default();
|
let node_id = current_element.source_node_id.map(|node_id| node_id.0).unwrap_or_default();
|
||||||
|
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
(group_index, vector_index, node_id).hash(&mut hasher);
|
(current_index, vector_index, node_id).hash(&mut hasher);
|
||||||
let collision_hash_seed = hasher.finish();
|
let collision_hash_seed = hasher.finish();
|
||||||
|
|
||||||
output.element.concat(other, transform, collision_hash_seed);
|
output.element.concat(other, transform, collision_hash_seed);
|
||||||
|
|
@ -985,13 +985,13 @@ where
|
||||||
output.element.style = row.element.style.clone();
|
output.element.style = row.element.style.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Graphic::Group(group) => {
|
Graphic::Group(graphic) => {
|
||||||
let mut group = group.clone();
|
let mut graphic = graphic.clone();
|
||||||
for row in group.iter_mut() {
|
for row in graphic.iter_mut() {
|
||||||
*row.transform = *current_element.transform * *row.transform;
|
*row.transform = *current_element.transform * *row.transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
flatten_group(&group, output);
|
flatten_table(output, &graphic);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -1000,13 +1000,11 @@ where
|
||||||
|
|
||||||
// Create a table with one empty `Vector` element, then get a mutable reference to it which we append flattened subpaths to
|
// Create a table with one empty `Vector` element, then get a mutable reference to it which we append flattened subpaths to
|
||||||
let mut output_table = Table::new_from_element(Vector::default());
|
let mut output_table = Table::new_from_element(Vector::default());
|
||||||
let Some(mut output) = output_table.iter_mut().next() else {
|
let Some(mut output) = output_table.iter_mut().next() else { return output_table };
|
||||||
return output_table;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Flatten the group input into the output `Vector` element
|
// Flatten the graphic input into the output `Vector` element
|
||||||
let base_group = Table::new_from_element(Graphic::from(content));
|
let base_graphic_table = Table::new_from_element(Graphic::from(content));
|
||||||
flatten_group(&base_group, &mut output);
|
flatten_table(&mut output, &base_graphic_table);
|
||||||
|
|
||||||
// Return the single-row Table<Vector> containing the flattened Vector subpaths
|
// Return the single-row Table<Vector> containing the flattened Vector subpaths
|
||||||
output_table
|
output_table
|
||||||
|
|
|
||||||
|
|
@ -348,21 +348,21 @@ fn random<U: num_traits::float::Float>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a number to an integer of the type u32, which may be the required type for certain node inputs. This will be removed in the future when automatic type conversion is implemented.
|
/// Convert a number to an integer of the type u32, which may be the required type for certain node inputs. This will be removed in the future when automatic type conversion is implemented.
|
||||||
#[node_macro::node(name("To u32"), category("Math: Numeric"))]
|
#[node_macro::node(name("To u32"), category("Type Conversion"))]
|
||||||
fn to_u32<U: num_traits::float::Float>(_: impl Ctx, #[implementations(f64, f32)] value: U) -> u32 {
|
fn to_u32<U: num_traits::float::Float>(_: impl Ctx, #[implementations(f64, f32)] value: U) -> u32 {
|
||||||
let value = U::clamp(value, U::from(0.).unwrap(), U::from(u32::MAX as f64).unwrap());
|
let value = U::clamp(value, U::from(0.).unwrap(), U::from(u32::MAX as f64).unwrap());
|
||||||
value.to_u32().unwrap()
|
value.to_u32().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a number to an integer of the type u64, which may be the required type for certain node inputs. This will be removed in the future when automatic type conversion is implemented.
|
/// Convert a number to an integer of the type u64, which may be the required type for certain node inputs. This will be removed in the future when automatic type conversion is implemented.
|
||||||
#[node_macro::node(name("To u64"), category("Math: Numeric"))]
|
#[node_macro::node(name("To u64"), category("Type Conversion"))]
|
||||||
fn to_u64<U: num_traits::float::Float>(_: impl Ctx, #[implementations(f64, f32)] value: U) -> u64 {
|
fn to_u64<U: num_traits::float::Float>(_: impl Ctx, #[implementations(f64, f32)] value: U) -> u64 {
|
||||||
let value = U::clamp(value, U::from(0.).unwrap(), U::from(u64::MAX as f64).unwrap());
|
let value = U::clamp(value, U::from(0.).unwrap(), U::from(u64::MAX as f64).unwrap());
|
||||||
value.to_u64().unwrap()
|
value.to_u64().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert an integer to a decimal number of the type f64, which may be the required type for certain node inputs. This will be removed in the future when automatic type conversion is implemented.
|
/// Convert an integer to a decimal number of the type f64, which may be the required type for certain node inputs. This will be removed in the future when automatic type conversion is implemented.
|
||||||
#[node_macro::node(name("To f64"), category("Math: Numeric"))]
|
#[node_macro::node(name("To f64"), category("Type Conversion"))]
|
||||||
fn to_f64<U: num_traits::int::PrimInt>(_: impl Ctx, #[implementations(u32, u64)] value: U) -> f64 {
|
fn to_f64<U: num_traits::int::PrimInt>(_: impl Ctx, #[implementations(u32, u64)] value: U) -> f64 {
|
||||||
value.to_f64().unwrap()
|
value.to_f64().unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -827,7 +827,7 @@ impl Render for Artboard {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contents group (includes the artwork but not the background)
|
// Content group (includes the artwork but not the background)
|
||||||
render.parent_tag(
|
render.parent_tag(
|
||||||
// SVG group tag
|
// SVG group tag
|
||||||
"g",
|
"g",
|
||||||
|
|
@ -851,7 +851,7 @@ impl Render for Artboard {
|
||||||
attributes.push("clip-path", selector);
|
attributes.push("clip-path", selector);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Artboard contents
|
// Artboard content
|
||||||
|render| {
|
|render| {
|
||||||
self.group.render_svg(render, render_params);
|
self.group.render_svg(render, render_params);
|
||||||
},
|
},
|
||||||
|
|
@ -1067,9 +1067,9 @@ impl Render for Table<Raster<CPU>> {
|
||||||
|
|
||||||
metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_subpath(subpath, 0.)]);
|
metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_subpath(subpath, 0.)]);
|
||||||
metadata.upstream_footprints.insert(element_id, footprint);
|
metadata.upstream_footprints.insert(element_id, footprint);
|
||||||
// TODO: Find a way to handle more than one row of the graphical data table
|
// TODO: Find a way to handle more than one row of the raster table
|
||||||
if let Some(image) = self.iter().next() {
|
if let Some(raster) = self.iter().next() {
|
||||||
metadata.local_transforms.insert(element_id, *image.transform);
|
metadata.local_transforms.insert(element_id, *raster.transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1125,9 +1125,9 @@ impl Render for Table<Raster<GPU>> {
|
||||||
|
|
||||||
metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_subpath(subpath, 0.)]);
|
metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_subpath(subpath, 0.)]);
|
||||||
metadata.upstream_footprints.insert(element_id, footprint);
|
metadata.upstream_footprints.insert(element_id, footprint);
|
||||||
// TODO: Find a way to handle more than one row of the graphical data table
|
// TODO: Find a way to handle more than one row of the raster table
|
||||||
if let Some(image) = self.iter().next() {
|
if let Some(raster) = self.iter().next() {
|
||||||
metadata.local_transforms.insert(element_id, *image.transform);
|
metadata.local_transforms.insert(element_id, *raster.transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1165,7 +1165,7 @@ impl Render for Graphic {
|
||||||
}
|
}
|
||||||
Graphic::Vector(vector) => {
|
Graphic::Vector(vector) => {
|
||||||
metadata.upstream_footprints.insert(element_id, footprint);
|
metadata.upstream_footprints.insert(element_id, footprint);
|
||||||
// TODO: Find a way to handle more than one row of the graphical data table
|
// TODO: Find a way to handle more than one row of the vector table
|
||||||
if let Some(vector) = vector.iter().next() {
|
if let Some(vector) = vector.iter().next() {
|
||||||
metadata.first_element_source_id.insert(element_id, *vector.source_node_id);
|
metadata.first_element_source_id.insert(element_id, *vector.source_node_id);
|
||||||
metadata.local_transforms.insert(element_id, *vector.transform);
|
metadata.local_transforms.insert(element_id, *vector.transform);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use dyn_any::StaticType;
|
use dyn_any::StaticType;
|
||||||
use glam::{DAffine2, DVec2, IVec2, UVec2};
|
use glam::{DAffine2, DVec2, IVec2};
|
||||||
use graph_craft::document::value::RenderOutput;
|
use graph_craft::document::value::RenderOutput;
|
||||||
use graph_craft::proto::{NodeConstructor, TypeErasedBox};
|
use graph_craft::proto::{NodeConstructor, TypeErasedBox};
|
||||||
use graphene_core::raster::color::Color;
|
use graphene_core::raster::color::Color;
|
||||||
|
|
@ -31,25 +31,33 @@ use wgpu_executor::{WgpuSurface, WindowHandle};
|
||||||
// TODO: turn into hashmap
|
// TODO: turn into hashmap
|
||||||
fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeConstructor>> {
|
fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeConstructor>> {
|
||||||
let mut node_types: Vec<(ProtoNodeIdentifier, NodeConstructor, NodeIOTypes)> = vec![
|
let mut node_types: Vec<(ProtoNodeIdentifier, NodeConstructor, NodeIOTypes)> = vec![
|
||||||
into_node!(from: Table<Vector>, to: Table<Vector>),
|
// ==========
|
||||||
into_node!(from: Table<Vector>, to: Graphic),
|
// INTO NODES
|
||||||
into_node!(from: Table<Vector>, to: Table<Graphic>),
|
// ==========
|
||||||
into_node!(from: Table<Graphic>, to: Table<Graphic>),
|
into_node!(from: Table<Graphic>, to: Table<Graphic>),
|
||||||
into_node!(from: Table<Graphic>, to: Graphic),
|
into_node!(from: Table<Vector>, to: Table<Vector>),
|
||||||
into_node!(from: Table<Raster<CPU>>, to: Table<Raster<CPU>>),
|
into_node!(from: Table<Raster<CPU>>, to: Table<Raster<CPU>>),
|
||||||
// into_node!(from: Table<Raster<CPU>>, to: Table<Raster<SRGBA8>>),
|
#[cfg(feature = "gpu")]
|
||||||
into_node!(from: Table<Raster<CPU>>, to: Graphic),
|
into_node!(from: Table<Raster<GPU>>, to: Table<Raster<GPU>>),
|
||||||
into_node!(from: Table<Raster<GPU>>, to: Graphic),
|
into_node!(from: Table<Vector>, to: Table<Graphic>),
|
||||||
into_node!(from: Table<Raster<CPU>>, to: Table<Graphic>),
|
into_node!(from: Table<Raster<CPU>>, to: Table<Graphic>),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Raster<CPU>>]),
|
#[cfg(feature = "gpu")]
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => ImageTexture]),
|
into_node!(from: Table<Raster<GPU>>, to: Table<Graphic>),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Vector>]),
|
// into_node!(from: Table<Raster<CPU>>, to: Table<Raster<SRGBA8>>),
|
||||||
|
#[cfg(feature = "gpu")]
|
||||||
|
into_node!(from: &WasmEditorApi, to: &WgpuExecutor),
|
||||||
|
// =============
|
||||||
|
// MONITOR NODES
|
||||||
|
// =============
|
||||||
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => ()]),
|
||||||
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Artboard>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Graphic>]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Graphic>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Graphic]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Vector>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Artboard]),
|
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Raster<CPU>>]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Raster<CPU>>]),
|
||||||
|
#[cfg(feature = "gpu")]
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::table::Table<Artboard>]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Color]),
|
||||||
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Option<Color>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => String]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => String]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => IVec2]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => IVec2]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => DVec2]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => DVec2]),
|
||||||
|
|
@ -58,12 +66,11 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => f64]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => f64]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => u32]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => u32]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => u64]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => u64]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => ()]),
|
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<f64>]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<f64>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => BlendMode]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => BlendMode]),
|
||||||
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => ImageTexture]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::transform::ReferencePoint]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::transform::ReferencePoint]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_path_bool::BooleanOperation]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_path_bool::BooleanOperation]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Option<Color>]),
|
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::Fill]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::Fill]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::StrokeCap]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::StrokeCap]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::StrokeJoin]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::StrokeJoin]),
|
||||||
|
|
@ -73,10 +80,12 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::Gradient]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::Gradient]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::GradientStops]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::GradientStops]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<graphene_core::uuid::NodeId>]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<graphene_core::uuid::NodeId>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Color]),
|
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Box<graphene_core::vector::VectorModification>]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Box<graphene_core::vector::VectorModification>]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::misc::CentroidType]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::misc::CentroidType]),
|
||||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::misc::PointSpacingType]),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::misc::PointSpacingType]),
|
||||||
|
// ==========
|
||||||
|
// MEMO NODES
|
||||||
|
// ==========
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Image<Color>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Image<Color>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Vector>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Vector>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Raster<CPU>>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Raster<CPU>>]),
|
||||||
|
|
@ -88,17 +97,28 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<WgpuSurface>]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<WgpuSurface>]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WindowHandle]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WindowHandle]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => SurfaceFrame]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => SurfaceFrame]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: UVec2, fn_params: [UVec2 => SurfaceFrame]),
|
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => f64]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => f64]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => String]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => String]),
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => RenderOutput]),
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => RenderOutput]),
|
||||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Graphic]),
|
#[cfg(feature = "gpu")]
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WgpuSurface]),
|
||||||
|
#[cfg(feature = "gpu")]
|
||||||
|
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
||||||
|
// =================
|
||||||
|
// IMPURE MEMO NODES
|
||||||
|
// =================
|
||||||
|
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Table<Artboard>]),
|
||||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Table<Graphic>]),
|
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Table<Graphic>]),
|
||||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Table<Vector>]),
|
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Table<Vector>]),
|
||||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Table<Graphic>]),
|
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Table<Raster<CPU>>]),
|
||||||
|
#[cfg(feature = "gpu")]
|
||||||
|
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
||||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => WgpuSurface]),
|
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => WgpuSurface]),
|
||||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Option<WgpuSurface>]),
|
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Option<WgpuSurface>]),
|
||||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => ImageTexture]),
|
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => ImageTexture]),
|
||||||
|
// ============
|
||||||
|
// COMPOSE NODE
|
||||||
|
// ============
|
||||||
(
|
(
|
||||||
ProtoNodeIdentifier::new("graphene_core::structural::ComposeNode"),
|
ProtoNodeIdentifier::new("graphene_core::structural::ComposeNode"),
|
||||||
|args| {
|
|args| {
|
||||||
|
|
@ -115,14 +135,9 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
vec![Type::Fn(Box::new(generic!(T)), Box::new(generic!(V))), Type::Fn(Box::new(generic!(V)), Box::new(generic!(U)))],
|
vec![Type::Fn(Box::new(generic!(T)), Box::new(generic!(V))), Type::Fn(Box::new(generic!(V)), Box::new(generic!(U)))],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
#[cfg(feature = "gpu")]
|
// =======================
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WgpuSurface]),
|
// CREATE GPU SURFACE NODE
|
||||||
#[cfg(feature = "gpu")]
|
// =======================
|
||||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
|
||||||
#[cfg(feature = "gpu")]
|
|
||||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
|
|
||||||
#[cfg(feature = "gpu")]
|
|
||||||
into_node!(from: &WasmEditorApi, to: &WgpuExecutor),
|
|
||||||
#[cfg(feature = "gpu")]
|
#[cfg(feature = "gpu")]
|
||||||
(
|
(
|
||||||
ProtoNodeIdentifier::new(stringify!(wgpu_executor::CreateGpuSurfaceNode<_>)),
|
ProtoNodeIdentifier::new(stringify!(wgpu_executor::CreateGpuSurfaceNode<_>)),
|
||||||
|
|
@ -143,6 +158,9 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
// =============
|
||||||
|
// CONVERT NODES
|
||||||
|
// =============
|
||||||
node_types.extend(
|
node_types.extend(
|
||||||
[
|
[
|
||||||
convert_node!(from: f32, to: numbers),
|
convert_node!(from: f32, to: numbers),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue