mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-03 13:02:20 +00:00
Make the node system use ImageFrame more extensively (#1055)
This commit is contained in:
parent
02d4565b0c
commit
0b813805d2
6 changed files with 215 additions and 158 deletions
|
@ -32,7 +32,7 @@ use document_legacy::layers::style::{Fill, RenderData, ViewMode};
|
||||||
use document_legacy::layers::text_layer::Font;
|
use document_legacy::layers::text_layer::Font;
|
||||||
use document_legacy::{DocumentError, DocumentResponse, LayerId, Operation as DocumentOperation};
|
use document_legacy::{DocumentError, DocumentResponse, LayerId, Operation as DocumentOperation};
|
||||||
use graph_craft::document::NodeId;
|
use graph_craft::document::NodeId;
|
||||||
use graphene_core::raster::color::Color;
|
use graphene_core::raster::{Color, ImageFrame};
|
||||||
use graphene_std::vector::subpath::Subpath;
|
use graphene_std::vector::subpath::Subpath;
|
||||||
|
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
|
@ -603,21 +603,37 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||||
PasteImage { image, mouse } => {
|
PasteImage { image, mouse } => {
|
||||||
let image_size = DVec2::new(image.width as f64, image.height as f64);
|
let image_size = DVec2::new(image.width as f64, image.height as f64);
|
||||||
|
|
||||||
responses.push_back(DocumentMessage::StartTransaction.into());
|
|
||||||
|
|
||||||
let path = vec![generate_uuid()];
|
|
||||||
let image_node_id = 100;
|
|
||||||
let mut network = crate::messages::portfolio::document::node_graph::new_image_network(32, image_node_id);
|
|
||||||
|
|
||||||
let Some(image_node_type) = crate::messages::portfolio::document::node_graph::resolve_document_node_type("Image") else {
|
let Some(image_node_type) = crate::messages::portfolio::document::node_graph::resolve_document_node_type("Image") else {
|
||||||
warn!("Image node should be in registry");
|
warn!("Image node should be in registry");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let path = vec![generate_uuid()];
|
||||||
|
let image_node_id = 100;
|
||||||
|
let mut network = crate::messages::portfolio::document::node_graph::new_image_network(32, image_node_id);
|
||||||
|
|
||||||
|
// Transform of parent folder
|
||||||
|
let to_parent_folder = self.document_legacy.generate_transform_across_scope(&path[..path.len() - 1], None).unwrap_or_default();
|
||||||
|
|
||||||
|
// Align the layer with the mouse or center of viewport
|
||||||
|
let viewport_location = mouse.map_or(ipp.viewport_bounds.center(), |pos| pos.into());
|
||||||
|
let center_in_viewport = DAffine2::from_translation(viewport_location - ipp.viewport_bounds.top_left);
|
||||||
|
let center_in_viewport_layerspace = to_parent_folder.inverse() * center_in_viewport;
|
||||||
|
|
||||||
|
// Make layer the size of the image
|
||||||
|
let fit_image_size = DAffine2::from_scale_angle_translation(image_size, 0., image_size / -2.);
|
||||||
|
|
||||||
|
let transform = (center_in_viewport_layerspace * fit_image_size);
|
||||||
|
|
||||||
|
responses.push_back(DocumentMessage::StartTransaction.into());
|
||||||
|
|
||||||
network.nodes.insert(
|
network.nodes.insert(
|
||||||
image_node_id,
|
image_node_id,
|
||||||
image_node_type.to_document_node(
|
image_node_type.to_document_node(
|
||||||
[graph_craft::document::NodeInput::value(graph_craft::document::value::TaggedValue::Image(image), false)],
|
[graph_craft::document::NodeInput::value(
|
||||||
|
graph_craft::document::value::TaggedValue::ImageFrame(ImageFrame { image, transform }),
|
||||||
|
false,
|
||||||
|
)],
|
||||||
graph_craft::document::DocumentNodeMetadata::position((20, 4)),
|
graph_craft::document::DocumentNodeMetadata::position((20, 4)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -638,19 +654,13 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Transform of parent folder
|
responses.push_back(
|
||||||
let to_parent_folder = self.document_legacy.generate_transform_across_scope(&path[..path.len() - 1], None).unwrap_or_default();
|
DocumentOperation::SetLayerTransform {
|
||||||
|
path,
|
||||||
// Align the layer with the mouse or center of viewport
|
transform: transform.to_cols_array(),
|
||||||
let viewport_location = mouse.map_or(ipp.viewport_bounds.center(), |pos| pos.into());
|
}
|
||||||
let center_in_viewport = DAffine2::from_translation(viewport_location - ipp.viewport_bounds.top_left);
|
.into(),
|
||||||
let center_in_viewport_layerspace = to_parent_folder.inverse() * center_in_viewport;
|
);
|
||||||
|
|
||||||
// Make layer the size of the image
|
|
||||||
let fit_image_size = DAffine2::from_scale_angle_translation(image_size, 0., image_size / -2.);
|
|
||||||
|
|
||||||
let transform = (center_in_viewport_layerspace * fit_image_size).to_cols_array();
|
|
||||||
responses.push_back(DocumentOperation::SetLayerTransform { path, transform }.into());
|
|
||||||
|
|
||||||
responses.push_back(DocumentMessage::NodeGraphFrameGenerate.into());
|
responses.push_back(DocumentMessage::NodeGraphFrameGenerate.into());
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
|
||||||
nodes: [
|
nodes: [
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
name: "Identity".to_string(),
|
name: "Identity".to_string(),
|
||||||
inputs: vec![NodeInput::Network(concrete!(Image))],
|
inputs: vec![NodeInput::Network(concrete!(ImageFrame))],
|
||||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")),
|
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")),
|
||||||
metadata: Default::default(),
|
metadata: Default::default(),
|
||||||
},
|
},
|
||||||
|
@ -154,13 +154,13 @@ fn static_nodes() -> Vec<DocumentNodeType> {
|
||||||
DocumentInputType {
|
DocumentInputType {
|
||||||
name: "In",
|
name: "In",
|
||||||
data_type: FrontendGraphDataType::General,
|
data_type: FrontendGraphDataType::General,
|
||||||
default: NodeInput::Network(concrete!(Image)),
|
default: NodeInput::Network(concrete!(ImageFrame)),
|
||||||
},
|
},
|
||||||
DocumentInputType::value("Transform", TaggedValue::DAffine2(DAffine2::IDENTITY), false),
|
DocumentInputType::value("Transform", TaggedValue::DAffine2(DAffine2::IDENTITY), false),
|
||||||
],
|
],
|
||||||
outputs: vec![
|
outputs: vec![
|
||||||
DocumentOutputType {
|
DocumentOutputType {
|
||||||
name: "Image",
|
name: "Image Frame",
|
||||||
data_type: FrontendGraphDataType::Raster,
|
data_type: FrontendGraphDataType::Raster,
|
||||||
},
|
},
|
||||||
DocumentOutputType {
|
DocumentOutputType {
|
||||||
|
@ -585,8 +585,8 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeType> = Lazy::new(|| DocumentNodeTyp
|
||||||
category: "Image Synthesis",
|
category: "Image Synthesis",
|
||||||
identifier: NodeImplementation::proto("graphene_std::raster::ImaginateNode<_>"),
|
identifier: NodeImplementation::proto("graphene_std::raster::ImaginateNode<_>"),
|
||||||
inputs: vec![
|
inputs: vec![
|
||||||
DocumentInputType::value("Input Image", TaggedValue::Image(Image::empty()), true),
|
DocumentInputType::value("Input Image", TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||||
DocumentInputType::value("Transform", TaggedValue::DAffine2(DAffine2::IDENTITY), true),
|
DocumentInputType::value("Transform", TaggedValue::DAffine2(DAffine2::IDENTITY), false),
|
||||||
DocumentInputType::value("Seed", TaggedValue::F64(0.), false), // Remember to keep index used in `NodeGraphFrameImaginateRandom` updated with this entry's index
|
DocumentInputType::value("Seed", TaggedValue::F64(0.), false), // Remember to keep index used in `NodeGraphFrameImaginateRandom` updated with this entry's index
|
||||||
DocumentInputType::value("Resolution", TaggedValue::OptionalDVec2(None), false),
|
DocumentInputType::value("Resolution", TaggedValue::OptionalDVec2(None), false),
|
||||||
DocumentInputType::value("Samples", TaggedValue::F64(30.), false),
|
DocumentInputType::value("Samples", TaggedValue::F64(30.), false),
|
||||||
|
@ -674,10 +674,7 @@ pub fn new_image_network(output_offset: i32, output_node_id: NodeId) -> NodeNetw
|
||||||
),
|
),
|
||||||
resolve_document_node_type("Output")
|
resolve_document_node_type("Output")
|
||||||
.expect("Output node does not exist")
|
.expect("Output node does not exist")
|
||||||
.to_document_node([NodeInput::node(2, 0)], DocumentNodeMetadata::position((output_offset + 8, 4))),
|
.to_document_node([NodeInput::node(output_node_id, 0)], DocumentNodeMetadata::position((output_offset + 8, 4))),
|
||||||
resolve_document_node_type("Image Frame")
|
|
||||||
.expect("Image frame node does not exist")
|
|
||||||
.to_document_node([NodeInput::node(output_node_id, 0), NodeInput::node(0, 1)], DocumentNodeMetadata::position((output_offset, 4))),
|
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
|
|
@ -19,17 +19,8 @@ pub struct NodeGraphExecutor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeGraphExecutor {
|
impl NodeGraphExecutor {
|
||||||
/// Sets the transform property on the input node
|
|
||||||
fn set_input_transform(network: &mut NodeNetwork, transform: DAffine2) {
|
|
||||||
let Some(input_node) = network.nodes.get_mut(&network.inputs[0]) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
input_node.inputs[1] = NodeInput::value(TaggedValue::DAffine2(transform), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Execute the network by flattening it and creating a borrow stack. Casts the output to the generic `T`.
|
/// Execute the network by flattening it and creating a borrow stack. Casts the output to the generic `T`.
|
||||||
fn execute_network<T: dyn_any::StaticType>(&mut self, mut network: NodeNetwork, image_frame: ImageFrame) -> Result<T, String> {
|
fn execute_network<T: dyn_any::StaticType>(&mut self, mut network: NodeNetwork, image_frame: ImageFrame) -> Result<T, String> {
|
||||||
Self::set_input_transform(&mut network, image_frame.transform);
|
|
||||||
network.duplicate_outputs(&mut generate_uuid);
|
network.duplicate_outputs(&mut generate_uuid);
|
||||||
network.remove_dead_nodes();
|
network.remove_dead_nodes();
|
||||||
|
|
||||||
|
@ -49,7 +40,7 @@ impl NodeGraphExecutor {
|
||||||
use dyn_any::IntoDynAny;
|
use dyn_any::IntoDynAny;
|
||||||
use graph_craft::executor::Executor;
|
use graph_craft::executor::Executor;
|
||||||
|
|
||||||
let boxed = self.executor.execute(image_frame.image.into_dyn()).map_err(|e| e.to_string())?;
|
let boxed = self.executor.execute(image_frame.into_dyn()).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
dyn_any::downcast::<T>(boxed).map(|v| *v)
|
dyn_any::downcast::<T>(boxed).map(|v| *v)
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,6 +291,7 @@ mod image {
|
||||||
use super::{Color, ImageSlice};
|
use super::{Color, ImageSlice};
|
||||||
use crate::Node;
|
use crate::Node;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use core::hash::{Hash, Hasher};
|
||||||
use dyn_any::{DynAny, StaticType};
|
use dyn_any::{DynAny, StaticType};
|
||||||
use glam::DAffine2;
|
use glam::DAffine2;
|
||||||
|
|
||||||
|
@ -389,6 +390,13 @@ mod image {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for ImageFrame {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.image.hash(state);
|
||||||
|
self.transform.to_cols_array().iter().for_each(|x| x.to_bits().hash(state))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use dyn_any::{DynAny, StaticType};
|
use dyn_any::{DynAny, StaticType};
|
||||||
|
|
||||||
use glam::DAffine2;
|
use glam::DAffine2;
|
||||||
use graphene_core::raster::{Color, Image};
|
use graphene_core::raster::{Color, Image, ImageFrame};
|
||||||
use graphene_core::Node;
|
use graphene_core::Node;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -107,6 +107,24 @@ where
|
||||||
image
|
image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct MapImageFrameNode<MapFn> {
|
||||||
|
map_fn: MapFn,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[node_macro::node_fn(MapImageFrameNode)]
|
||||||
|
fn map_image<MapFn>(mut image_frame: ImageFrame, map_fn: &'any_input MapFn) -> ImageFrame
|
||||||
|
where
|
||||||
|
MapFn: for<'any_input> Node<'any_input, Color, Output = Color> + 'input,
|
||||||
|
{
|
||||||
|
let mut image_frame = image_frame;
|
||||||
|
for pixel in &mut image_frame.image.data {
|
||||||
|
*pixel = map_fn.eval(*pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
image_frame
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct BlendImageNode<Second, MapFn> {
|
pub struct BlendImageNode<Second, MapFn> {
|
||||||
second: Second,
|
second: Second,
|
||||||
|
@ -131,9 +149,13 @@ pub struct ImaginateNode<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node_fn(ImaginateNode)]
|
#[node_macro::node_fn(ImaginateNode)]
|
||||||
fn imaginate(image: Image, cached: Option<std::sync::Arc<graphene_core::raster::Image>>) -> Image {
|
fn imaginate(image_frame: ImageFrame, cached: Option<std::sync::Arc<graphene_core::raster::Image>>) -> ImageFrame {
|
||||||
info!("Imaginating image with {} pixels", image.data.len());
|
info!("Imaginating image with {} pixels", image_frame.image.data.len());
|
||||||
cached.map(|mut x| std::sync::Arc::make_mut(&mut x).clone()).unwrap_or(image)
|
let cached_image = cached.map(|mut x| std::sync::Arc::make_mut(&mut x).clone()).unwrap_or(image_frame.image);
|
||||||
|
ImageFrame {
|
||||||
|
image: cached_image,
|
||||||
|
transform: image_frame.transform,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|
|
@ -10,7 +10,7 @@ use graphene_core::structural::Then;
|
||||||
use graphene_core::value::{ClonedNode, ForgetNode, ValueNode};
|
use graphene_core::value::{ClonedNode, ForgetNode, ValueNode};
|
||||||
use graphene_core::{Node, NodeIO, NodeIOTypes};
|
use graphene_core::{Node, NodeIO, NodeIOTypes};
|
||||||
|
|
||||||
use graphene_std::any::{ComposeTypeErased, DowncastBothNode, DowncastBothRefNode, DynAnyNode, IntoTypeErasedNode};
|
use graphene_std::any::{ComposeTypeErased, DowncastBothNode, DowncastBothRefNode, DynAnyNode, IntoTypeErasedNode, TypeErasedPinnedRef};
|
||||||
|
|
||||||
use graphene_core::{Cow, NodeIdentifier, Type, TypeDescriptor};
|
use graphene_core::{Cow, NodeIdentifier, Type, TypeDescriptor};
|
||||||
|
|
||||||
|
@ -23,18 +23,25 @@ use crate::executor::NodeContainer;
|
||||||
|
|
||||||
use dyn_any::StaticType;
|
use dyn_any::StaticType;
|
||||||
|
|
||||||
|
macro_rules! construct_node {
|
||||||
|
($args: ident, $path:ty, [$($type:tt),*]) => {{
|
||||||
|
let mut args: Vec<TypeErasedPinnedRef<'static>> = $args.clone();
|
||||||
|
args.reverse();
|
||||||
|
<$path>::new($(graphene_core::value::ClonedNode::new(
|
||||||
|
graphene_std::any::input_node::<$type>(args.pop()
|
||||||
|
.expect("Not enough arguments provided to construct node"))).eval(())
|
||||||
|
),*
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! register_node {
|
macro_rules! register_node {
|
||||||
($path:ty, input: $input:ty, params: [$($type:ty),*]) => {
|
($path:ty, input: $input:ty, params: [$($type:ty),*]) => {
|
||||||
|
vec![
|
||||||
(
|
(
|
||||||
NodeIdentifier::new(stringify!($path)),
|
NodeIdentifier::new(stringify!($path)),
|
||||||
|args| {
|
|args| {
|
||||||
let mut args = args.clone();
|
let node = construct_node!(args, $path, [$($type),*]);
|
||||||
args.reverse();
|
|
||||||
let node = <$path>::new($(
|
|
||||||
graphene_std::any::input_node::<$type>(
|
|
||||||
args.pop().expect("not enough arguments provided to construct node")
|
|
||||||
)
|
|
||||||
),*);
|
|
||||||
let any: DynAnyNode<$input, _, _> = graphene_std::any::DynAnyNode::new(graphene_core::value::ValueNode::new(node));
|
let any: DynAnyNode<$input, _, _> = graphene_std::any::DynAnyNode::new(graphene_core::value::ValueNode::new(node));
|
||||||
Box::pin(any)
|
Box::pin(any)
|
||||||
},
|
},
|
||||||
|
@ -51,22 +58,28 @@ macro_rules! register_node {
|
||||||
node_io
|
node_io
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
macro_rules! raster_node {
|
macro_rules! raster_node {
|
||||||
($path:ty, params: [$($type:ty),*]) => {
|
($path:ty, params: [$($type:ty),*]) => {
|
||||||
|
vec![
|
||||||
(
|
(
|
||||||
NodeIdentifier::new(stringify!($path)),
|
NodeIdentifier::new(stringify!($path)),
|
||||||
|args| {
|
|args| {
|
||||||
let mut args = args.clone();
|
let node = construct_node!(args, $path, [$($type),*]);
|
||||||
args.reverse();
|
let any: DynAnyNode<Color, _, _> = graphene_std::any::DynAnyNode::new(graphene_core::value::ValueNode::new(node));
|
||||||
let node = <$path>::new($(
|
Box::pin(any)
|
||||||
graphene_core::value::ClonedNode::new(
|
},
|
||||||
graphene_std::any::input_node::<$type>(
|
{
|
||||||
args.pop().expect("Not enough arguments provided to construct node")
|
let params = vec![$((concrete!(()), concrete!($type))),*];
|
||||||
).eval(())
|
NodeIOTypes::new(concrete!(Color), concrete!(Color), params)
|
||||||
)
|
},
|
||||||
),*);
|
),
|
||||||
|
(
|
||||||
|
NodeIdentifier::new(stringify!($path)),
|
||||||
|
|args| {
|
||||||
|
let node = construct_node!(args, $path, [$($type),*]);
|
||||||
let map_node = graphene_std::raster::MapImageNode::new(graphene_core::value::ValueNode::new(node));
|
let map_node = graphene_std::raster::MapImageNode::new(graphene_core::value::ValueNode::new(node));
|
||||||
let any: DynAnyNode<Image, _, _> = graphene_std::any::DynAnyNode::new(graphene_core::value::ValueNode::new(map_node));
|
let any: DynAnyNode<Image, _, _> = graphene_std::any::DynAnyNode::new(graphene_core::value::ValueNode::new(map_node));
|
||||||
Box::pin(any)
|
Box::pin(any)
|
||||||
|
@ -75,19 +88,33 @@ macro_rules! raster_node {
|
||||||
let params = vec![$((concrete!(()), concrete!($type))),*];
|
let params = vec![$((concrete!(()), concrete!($type))),*];
|
||||||
NodeIOTypes::new(concrete!(Image), concrete!(Image), params)
|
NodeIOTypes::new(concrete!(Image), concrete!(Image), params)
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
NodeIdentifier::new(stringify!($path)),
|
||||||
|
|args| {
|
||||||
|
let node = construct_node!(args, $path, [$($type),*]);
|
||||||
|
let map_node = graphene_std::raster::MapImageFrameNode::new(graphene_core::value::ValueNode::new(node));
|
||||||
|
let any: DynAnyNode<ImageFrame, _, _> = graphene_std::any::DynAnyNode::new(graphene_core::value::ValueNode::new(map_node));
|
||||||
|
Box::pin(any)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
let params = vec![$((concrete!(()), concrete!($type))),*];
|
||||||
|
NodeIOTypes::new(concrete!(ImageFrame), concrete!(ImageFrame), params)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
};
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: turn into hashmap
|
//TODO: turn into hashmap
|
||||||
fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstructor>> {
|
fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstructor>> {
|
||||||
let node_types: Vec<(NodeIdentifier, NodeConstructor, NodeIOTypes)> = vec![
|
let node_types: Vec<Vec<(NodeIdentifier, NodeConstructor, NodeIOTypes)>> = vec![
|
||||||
//register_node!(graphene_core::ops::IdNode, input: Any<'_>, params: []),
|
//register_node!(graphene_core::ops::IdNode, input: Any<'_>, params: []),
|
||||||
(
|
vec![(
|
||||||
NodeIdentifier::new("graphene_core::ops::IdNode"),
|
NodeIdentifier::new("graphene_core::ops::IdNode"),
|
||||||
|_| IdNode::new().into_type_erased(),
|
|_| IdNode::new().into_type_erased(),
|
||||||
NodeIOTypes::new(generic!(I), generic!(I), vec![]),
|
NodeIOTypes::new(generic!(I), generic!(I), vec![]),
|
||||||
),
|
)],
|
||||||
// TODO: create macro to impl for all types
|
// TODO: create macro to impl for all types
|
||||||
register_node!(graphene_core::structural::ConsNode<_, _>, input: u32, params: [u32]),
|
register_node!(graphene_core::structural::ConsNode<_, _>, input: u32, params: [u32]),
|
||||||
register_node!(graphene_core::structural::ConsNode<_, _>, input: u32, params: [&u32]),
|
register_node!(graphene_core::structural::ConsNode<_, _>, input: u32, params: [&u32]),
|
||||||
|
@ -104,18 +131,18 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
|
||||||
register_node!(graphene_core::ops::AddParameterNode<_>, input: &f64, params: [f64]),
|
register_node!(graphene_core::ops::AddParameterNode<_>, input: &f64, params: [f64]),
|
||||||
register_node!(graphene_core::ops::AddParameterNode<_>, input: f64, params: [&f64]),
|
register_node!(graphene_core::ops::AddParameterNode<_>, input: f64, params: [&f64]),
|
||||||
register_node!(graphene_core::ops::AddParameterNode<_>, input: &f64, params: [&f64]),
|
register_node!(graphene_core::ops::AddParameterNode<_>, input: &f64, params: [&f64]),
|
||||||
(
|
vec![(
|
||||||
NodeIdentifier::new("graphene_core::structural::ComposeNode<_, _, _>"),
|
NodeIdentifier::new("graphene_core::structural::ComposeNode<_, _, _>"),
|
||||||
|args| {
|
|args| {
|
||||||
let node = ComposeTypeErased::new(args[0], args[1]);
|
let node = ComposeTypeErased::new(args[0], args[1]);
|
||||||
node.into_type_erased()
|
node.into_type_erased()
|
||||||
},
|
},
|
||||||
NodeIOTypes::new(generic!(T), generic!(U), vec![(generic!(T), generic!(V)), (generic!(V), generic!(U))]),
|
NodeIOTypes::new(generic!(T), generic!(U), vec![(generic!(T), generic!(V)), (generic!(V), generic!(U))]),
|
||||||
),
|
)],
|
||||||
// Filters
|
// Filters
|
||||||
raster_node!(graphene_core::raster::LuminanceNode<_>, params: [LuminanceCalculation]),
|
raster_node!(graphene_core::raster::LuminanceNode<_>, params: [LuminanceCalculation]),
|
||||||
raster_node!(graphene_core::raster::LevelsNode<_, _, _, _, _>, params: [f64, f64, f64, f64, f64]),
|
raster_node!(graphene_core::raster::LevelsNode<_, _, _, _, _>, params: [f64, f64, f64, f64, f64]),
|
||||||
(
|
vec![(
|
||||||
NodeIdentifier::new("graphene_core::raster::BlendNode<_, _, _, _>"),
|
NodeIdentifier::new("graphene_core::raster::BlendNode<_, _, _, _>"),
|
||||||
|args| {
|
|args| {
|
||||||
use graphene_core::Node;
|
use graphene_core::Node;
|
||||||
|
@ -133,7 +160,7 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
|
||||||
concrete!(Image),
|
concrete!(Image),
|
||||||
vec![(concrete!(()), concrete!(Image)), (concrete!(()), concrete!(BlendMode)), (concrete!(()), concrete!(f64))],
|
vec![(concrete!(()), concrete!(Image)), (concrete!(()), concrete!(BlendMode)), (concrete!(()), concrete!(f64))],
|
||||||
),
|
),
|
||||||
),
|
)],
|
||||||
raster_node!(graphene_core::raster::GrayscaleNode<_, _, _, _, _, _, _>, params: [Color, f64, f64, f64, f64, f64, f64]),
|
raster_node!(graphene_core::raster::GrayscaleNode<_, _, _, _, _, _, _>, params: [Color, f64, f64, f64, f64, f64, f64]),
|
||||||
raster_node!(graphene_core::raster::HueSaturationNode<_, _, _>, params: [f64, f64, f64]),
|
raster_node!(graphene_core::raster::HueSaturationNode<_, _, _>, params: [f64, f64, f64]),
|
||||||
raster_node!(graphene_core::raster::InvertRGBNode, params: []),
|
raster_node!(graphene_core::raster::InvertRGBNode, params: []),
|
||||||
|
@ -143,97 +170,99 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
|
||||||
raster_node!(graphene_core::raster::OpacityNode<_>, params: [f64]),
|
raster_node!(graphene_core::raster::OpacityNode<_>, params: [f64]),
|
||||||
raster_node!(graphene_core::raster::PosterizeNode<_>, params: [f64]),
|
raster_node!(graphene_core::raster::PosterizeNode<_>, params: [f64]),
|
||||||
raster_node!(graphene_core::raster::ExposureNode<_, _, _>, params: [f64, f64, f64]),
|
raster_node!(graphene_core::raster::ExposureNode<_, _, _>, params: [f64, f64, f64]),
|
||||||
(
|
vec![
|
||||||
NodeIdentifier::new("graphene_core::structural::MapImageNode"),
|
(
|
||||||
|args| {
|
NodeIdentifier::new("graphene_core::structural::MapImageNode"),
|
||||||
let map_fn: DowncastBothNode<Color, Color> = DowncastBothNode::new(args[0]);
|
|args| {
|
||||||
let node = graphene_std::raster::MapImageNode::new(ValueNode::new(map_fn));
|
let map_fn: DowncastBothNode<Color, Color> = DowncastBothNode::new(args[0]);
|
||||||
let any: DynAnyNode<Image, _, _> = graphene_std::any::DynAnyNode::new(graphene_core::value::ValueNode::new(node));
|
let node = graphene_std::raster::MapImageNode::new(ValueNode::new(map_fn));
|
||||||
any.into_type_erased()
|
let any: DynAnyNode<Image, _, _> = graphene_std::any::DynAnyNode::new(graphene_core::value::ValueNode::new(node));
|
||||||
},
|
any.into_type_erased()
|
||||||
NodeIOTypes::new(concrete!(Image), concrete!(Image), vec![]),
|
},
|
||||||
),
|
NodeIOTypes::new(concrete!(Image), concrete!(Image), vec![]),
|
||||||
(
|
|
||||||
NodeIdentifier::new("graphene_std::raster::ImaginateNode<_>"),
|
|
||||||
|args| {
|
|
||||||
let cached = graphene_std::any::input_node::<Option<std::sync::Arc<Image>>>(args[16]);
|
|
||||||
let node = graphene_std::raster::ImaginateNode::new(cached);
|
|
||||||
let any = DynAnyNode::new(ValueNode::new(node));
|
|
||||||
any.into_type_erased()
|
|
||||||
},
|
|
||||||
NodeIOTypes::new(
|
|
||||||
concrete!(Image),
|
|
||||||
concrete!(Image),
|
|
||||||
vec![
|
|
||||||
(concrete!(()), concrete!(DAffine2)),
|
|
||||||
(concrete!(()), concrete!(f64)),
|
|
||||||
(concrete!(()), concrete!(Option<DVec2>)),
|
|
||||||
(concrete!(()), concrete!(f64)),
|
|
||||||
(concrete!(()), concrete!(ImaginateSamplingMethod)),
|
|
||||||
(concrete!(()), concrete!(f64)),
|
|
||||||
(concrete!(()), concrete!(String)),
|
|
||||||
(concrete!(()), concrete!(String)),
|
|
||||||
(concrete!(()), concrete!(bool)),
|
|
||||||
(concrete!(()), concrete!(f64)),
|
|
||||||
(concrete!(()), concrete!(Option<Vec<u64>>)),
|
|
||||||
(concrete!(()), concrete!(bool)),
|
|
||||||
(concrete!(()), concrete!(f64)),
|
|
||||||
(concrete!(()), concrete!(ImaginateMaskStartingFill)),
|
|
||||||
(concrete!(()), concrete!(bool)),
|
|
||||||
(concrete!(()), concrete!(bool)),
|
|
||||||
(concrete!(()), concrete!(Option<std::sync::Arc<Image>>)),
|
|
||||||
(concrete!(()), concrete!(f64)),
|
|
||||||
(concrete!(()), concrete!(ImaginateStatus)),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
(
|
||||||
(
|
NodeIdentifier::new("graphene_std::raster::ImaginateNode<_>"),
|
||||||
NodeIdentifier::new("graphene_core::raster::BlurNode"),
|
|args| {
|
||||||
|args| {
|
let cached = graphene_std::any::input_node::<Option<std::sync::Arc<Image>>>(args[16]);
|
||||||
let radius = DowncastBothNode::<(), u32>::new(args[0]);
|
let node = graphene_std::raster::ImaginateNode::new(cached);
|
||||||
let sigma = DowncastBothNode::<(), f64>::new(args[1]);
|
let any = DynAnyNode::new(ValueNode::new(node));
|
||||||
let image = DowncastBothRefNode::<Image, Image>::new(args[2]);
|
any.into_type_erased()
|
||||||
let empty_image: ValueNode<Image> = ValueNode::new(Image::empty());
|
},
|
||||||
let empty: TypeNode<_, (), Image> = TypeNode::new(empty_image.then(CloneNode::new()));
|
NodeIOTypes::new(
|
||||||
use graphene_core::Node;
|
concrete!(ImageFrame),
|
||||||
let radius = ClonedNode::new(radius.eval(()));
|
concrete!(ImageFrame),
|
||||||
let sigma = ClonedNode::new(sigma.eval(()));
|
vec![
|
||||||
|
(concrete!(()), concrete!(DAffine2)),
|
||||||
|
(concrete!(()), concrete!(f64)),
|
||||||
|
(concrete!(()), concrete!(Option<DVec2>)),
|
||||||
|
(concrete!(()), concrete!(f64)),
|
||||||
|
(concrete!(()), concrete!(ImaginateSamplingMethod)),
|
||||||
|
(concrete!(()), concrete!(f64)),
|
||||||
|
(concrete!(()), concrete!(String)),
|
||||||
|
(concrete!(()), concrete!(String)),
|
||||||
|
(concrete!(()), concrete!(bool)),
|
||||||
|
(concrete!(()), concrete!(f64)),
|
||||||
|
(concrete!(()), concrete!(Option<Vec<u64>>)),
|
||||||
|
(concrete!(()), concrete!(bool)),
|
||||||
|
(concrete!(()), concrete!(f64)),
|
||||||
|
(concrete!(()), concrete!(ImaginateMaskStartingFill)),
|
||||||
|
(concrete!(()), concrete!(bool)),
|
||||||
|
(concrete!(()), concrete!(bool)),
|
||||||
|
(concrete!(()), concrete!(Option<std::sync::Arc<Image>>)),
|
||||||
|
(concrete!(()), concrete!(f64)),
|
||||||
|
(concrete!(()), concrete!(ImaginateStatus)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
NodeIdentifier::new("graphene_core::raster::BlurNode"),
|
||||||
|
|args| {
|
||||||
|
let radius = DowncastBothNode::<(), u32>::new(args[0]);
|
||||||
|
let sigma = DowncastBothNode::<(), f64>::new(args[1]);
|
||||||
|
let image = DowncastBothRefNode::<Image, Image>::new(args[2]);
|
||||||
|
let empty_image: ValueNode<Image> = ValueNode::new(Image::empty());
|
||||||
|
let empty: TypeNode<_, (), Image> = TypeNode::new(empty_image.then(CloneNode::new()));
|
||||||
|
use graphene_core::Node;
|
||||||
|
let radius = ClonedNode::new(radius.eval(()));
|
||||||
|
let sigma = ClonedNode::new(sigma.eval(()));
|
||||||
|
|
||||||
//let image = &image as &dyn for<'a> Node<'a, (), Output = &'a Image>;
|
//let image = &image as &dyn for<'a> Node<'a, (), Output = &'a Image>;
|
||||||
// dirty hack: we abuse that the cache node will ignore the input if it is evaluated a second time
|
// dirty hack: we abuse that the cache node will ignore the input if it is evaluated a second time
|
||||||
let image = empty.then(image).then(ImageRefNode::new());
|
let image = empty.then(image).then(ImageRefNode::new());
|
||||||
|
|
||||||
let window = WindowNode::new(radius, image.clone());
|
let window = WindowNode::new(radius, image.clone());
|
||||||
let map_gaussian = MapSndNode::new(ValueNode::new(DistanceNode.then(GaussianNode::new(sigma))));
|
let map_gaussian = MapSndNode::new(ValueNode::new(DistanceNode.then(GaussianNode::new(sigma))));
|
||||||
let map_distances = MapNode::new(ValueNode::new(map_gaussian));
|
let map_distances = MapNode::new(ValueNode::new(map_gaussian));
|
||||||
let gaussian_iter = window.then(map_distances);
|
let gaussian_iter = window.then(map_distances);
|
||||||
let avg = gaussian_iter.then(WeightedAvgNode::new());
|
let avg = gaussian_iter.then(WeightedAvgNode::new());
|
||||||
let avg: TypeNode<_, u32, Color> = TypeNode::new(avg);
|
let avg: TypeNode<_, u32, Color> = TypeNode::new(avg);
|
||||||
let blur_iter = MapNode::new(ValueNode::new(avg));
|
let blur_iter = MapNode::new(ValueNode::new(avg));
|
||||||
let pixel_iter = image.clone().then(ImageIndexIterNode::new());
|
let pixel_iter = image.clone().then(ImageIndexIterNode::new());
|
||||||
let blur = pixel_iter.then(blur_iter);
|
let blur = pixel_iter.then(blur_iter);
|
||||||
let collect = CollectNode {};
|
let collect = CollectNode {};
|
||||||
let vec = blur.then(collect);
|
let vec = blur.then(collect);
|
||||||
let new_image = MapImageSliceNode::new(vec);
|
let new_image = MapImageSliceNode::new(vec);
|
||||||
let dimensions = image.then(ImageDimensionsNode::new());
|
let dimensions = image.then(ImageDimensionsNode::new());
|
||||||
let dimensions: TypeNode<_, (), (u32, u32)> = TypeNode::new(dimensions);
|
let dimensions: TypeNode<_, (), (u32, u32)> = TypeNode::new(dimensions);
|
||||||
let new_image = dimensions.then(new_image);
|
let new_image = dimensions.then(new_image);
|
||||||
let new_image = ForgetNode::new().then(new_image);
|
let new_image = ForgetNode::new().then(new_image);
|
||||||
let node: DynAnyNode<&Image, _, _> = DynAnyNode::new(ValueNode::new(new_image));
|
let node: DynAnyNode<&Image, _, _> = DynAnyNode::new(ValueNode::new(new_image));
|
||||||
node.into_type_erased()
|
node.into_type_erased()
|
||||||
},
|
},
|
||||||
NodeIOTypes::new(concrete!(Image), concrete!(Image), vec![(concrete!(()), concrete!(u32)), (concrete!(()), concrete!(f64))]),
|
NodeIOTypes::new(concrete!(Image), concrete!(Image), vec![(concrete!(()), concrete!(u32)), (concrete!(()), concrete!(f64))]),
|
||||||
),
|
),
|
||||||
//register_node!(graphene_std::memo::CacheNode<_>, input: Image, params: []),
|
//register_node!(graphene_std::memo::CacheNode<_>, input: Image, params: []),
|
||||||
(
|
(
|
||||||
NodeIdentifier::new("graphene_std::memo::CacheNode"),
|
NodeIdentifier::new("graphene_std::memo::CacheNode"),
|
||||||
|_| {
|
|_| {
|
||||||
let node: CacheNode<Image> = graphene_std::memo::CacheNode::new();
|
let node: CacheNode<Image> = graphene_std::memo::CacheNode::new();
|
||||||
let any = graphene_std::any::DynAnyRefNode::new(node);
|
let any = graphene_std::any::DynAnyRefNode::new(node);
|
||||||
any.into_type_erased()
|
any.into_type_erased()
|
||||||
},
|
},
|
||||||
NodeIOTypes::new(concrete!(Image), concrete!(&Image), vec![]),
|
NodeIOTypes::new(concrete!(Image), concrete!(&Image), vec![]),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
register_node!(graphene_core::structural::ConsNode<_, _>, input: Image, params: [&str]),
|
register_node!(graphene_core::structural::ConsNode<_, _>, input: Image, params: [&str]),
|
||||||
register_node!(graphene_std::raster::ImageFrameNode<_>, input: Image, params: [DAffine2]),
|
register_node!(graphene_std::raster::ImageFrameNode<_>, input: Image, params: [DAffine2]),
|
||||||
/*
|
/*
|
||||||
|
@ -390,7 +419,7 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
|
||||||
*/
|
*/
|
||||||
];
|
];
|
||||||
let mut map: HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstructor>> = HashMap::new();
|
let mut map: HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstructor>> = HashMap::new();
|
||||||
for (id, c, types) in node_types {
|
for (id, c, types) in node_types.into_iter().flatten() {
|
||||||
map.entry(id).or_default().insert(types.clone(), c);
|
map.entry(id).or_default().insert(types.clone(), c);
|
||||||
}
|
}
|
||||||
map
|
map
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue