diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index f73d31e5..c79bd1b7 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -124,6 +124,33 @@ static DOCUMENT_NODE_TYPES: once_cell::sync::Lazy> = once_ // TODO: Dynamic node library fn static_nodes() -> Vec { vec![ + DocumentNodeType { + name: "Boolean", + category: "Inputs", + identifier: NodeImplementation::proto("graphene_core::ops::IdNode"), + inputs: vec![DocumentInputType::value("Bool", TaggedValue::Bool(true), false)], + outputs: vec![DocumentOutputType::new("Out", FrontendGraphDataType::Boolean)], + properties: node_properties::boolean_properties, + ..Default::default() + }, + DocumentNodeType { + name: "Value", + category: "Inputs", + identifier: NodeImplementation::proto("graphene_core::ops::IdNode"), + inputs: vec![DocumentInputType::value("Value", TaggedValue::F32(0.), false)], + outputs: vec![DocumentOutputType::new("Out", FrontendGraphDataType::Number)], + properties: node_properties::value_properties, + ..Default::default() + }, + DocumentNodeType { + name: "Color", + category: "Inputs", + identifier: NodeImplementation::proto("graphene_core::ops::IdNode"), + inputs: vec![DocumentInputType::value("Value", TaggedValue::OptionalColor(None), false)], + outputs: vec![DocumentOutputType::new("Out", FrontendGraphDataType::Color)], + properties: node_properties::color_properties, + ..Default::default() + }, DocumentNodeType { name: "Identity", category: "Structural", @@ -665,6 +692,24 @@ fn static_nodes() -> Vec { properties: node_properties::grayscale_properties, ..Default::default() }, + DocumentNodeType { + name: "Color Channel", + category: "Image Adjustments", + identifier: NodeImplementation::proto("graphene_core::ops::IdNode"), + inputs: vec![DocumentInputType::value("Channel", TaggedValue::RedGreenBlue(RedGreenBlue::Red), false)], + outputs: vec![DocumentOutputType::new("Out", FrontendGraphDataType::General)], + properties: node_properties::color_channel_properties, + ..Default::default() + }, + DocumentNodeType { + name: "Blend Mode", + category: "Image Adjustments", + identifier: NodeImplementation::proto("graphene_core::ops::IdNode"), + inputs: vec![DocumentInputType::value("Mode", TaggedValue::BlendMode(BlendMode::Normal), false)], + outputs: vec![DocumentOutputType::new("Out", FrontendGraphDataType::General)], + properties: node_properties::blend_mode_properties, + ..Default::default() + }, DocumentNodeType { name: "Luminance", category: "Image Adjustments", @@ -1645,13 +1690,73 @@ fn static_nodes() -> Vec { category: "Math", identifier: NodeImplementation::proto("graphene_core::ops::AddParameterNode<_>"), inputs: vec![ - DocumentInputType::value("Input", TaggedValue::F32(0.), true), - DocumentInputType::value("Addend", TaggedValue::F32(0.), true), + DocumentInputType::value("Primary", TaggedValue::F32(0.), true), + DocumentInputType::value("Addend", TaggedValue::F32(0.), false), ], outputs: vec![DocumentOutputType::new("Output", FrontendGraphDataType::Number)], properties: node_properties::add_properties, ..Default::default() }, + DocumentNodeType { + name: "Subtract", + category: "Math", + identifier: NodeImplementation::proto("graphene_core::ops::AddParameterNode<_>"), + inputs: vec![ + DocumentInputType::value("Primary", TaggedValue::F32(0.), true), + DocumentInputType::value("Subtrahend", TaggedValue::F32(0.), false), + ], + outputs: vec![DocumentOutputType::new("Output", FrontendGraphDataType::Number)], + properties: node_properties::subtract_properties, + ..Default::default() + }, + DocumentNodeType { + name: "Divide", + category: "Math", + identifier: NodeImplementation::proto("graphene_core::ops::DivideParameterNode<_>"), + inputs: vec![ + DocumentInputType::value("Primary", TaggedValue::F32(0.), true), + DocumentInputType::value("Divisor", TaggedValue::F32(0.), false), + ], + outputs: vec![DocumentOutputType::new("Output", FrontendGraphDataType::Number)], + properties: node_properties::divide_properties, + ..Default::default() + }, + DocumentNodeType { + name: "Multiply", + category: "Math", + identifier: NodeImplementation::proto("graphene_core::ops::MultiplyParameterNode<_>"), + inputs: vec![ + DocumentInputType::value("Primary", TaggedValue::F32(0.), true), + DocumentInputType::value("Multiplicand", TaggedValue::F32(0.), false), + ], + outputs: vec![DocumentOutputType::new("Output", FrontendGraphDataType::Number)], + properties: node_properties::multiply_properties, + ..Default::default() + }, + DocumentNodeType { + name: "Exponent", + category: "Math", + identifier: NodeImplementation::proto("graphene_core::ops::ExponentParameterNode<_>"), + inputs: vec![ + DocumentInputType::value("Primary", TaggedValue::F32(0.), true), + DocumentInputType::value("Power", TaggedValue::F32(0.), false), + ], + outputs: vec![DocumentOutputType::new("Output", FrontendGraphDataType::Number)], + properties: node_properties::exponent_properties, + ..Default::default() + }, + DocumentNodeType { + name: "Modulo", + category: "Math", + identifier: NodeImplementation::proto("graphene_core::ops::ModuloParameterNode<_>"), + inputs: vec![ + DocumentInputType::value("Primary", TaggedValue::F32(0.), true), + DocumentInputType::value("Modulus", TaggedValue::F32(0.), false), + ], + outputs: vec![DocumentOutputType::new("Output", FrontendGraphDataType::Number)], + properties: node_properties::modulo_properties, + ..Default::default() + }, (*IMAGINATE_NODE).clone(), DocumentNodeType { name: "Unit Circle Generator", diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index 1f906de3..b1c385c1 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -639,6 +639,33 @@ pub fn blend_properties(document_node: &DocumentNode, node_id: NodeId, _context: vec![backdrop, blend_mode, LayoutGroup::Row { widgets: opacity }] } +pub fn value_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let widgets = number_widget(document_node, node_id, index, name, NumberInput::default(), true); + + LayoutGroup::Row { widgets } + }; + vec![operand("Value", 0)] +} + +pub fn boolean_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let widgets = bool_widget(document_node, node_id, index, name, true); + + LayoutGroup::Row { widgets } + }; + vec![operand("Bool", 0)] +} + +pub fn color_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let color = color_widget(document_node, node_id, index, name, ColorInput::default(), true); + + color + }; + vec![operand("Color", 0)] +} + pub fn load_image_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let url = text_widget(document_node, node_id, 1, "Url", true); @@ -682,6 +709,24 @@ pub fn mask_properties(document_node: &DocumentNode, node_id: NodeId, _context: vec![mask] } +pub fn blend_mode_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let blend_mode = blend_mode(document_node, node_id, index, name, true); + + blend_mode + }; + vec![operand("Blend Mode", 0)] +} + +pub fn color_channel_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let color_channel = color_channel(document_node, node_id, index, name, true); + + color_channel + }; + vec![operand("Channel", 0)] +} + pub fn luminance_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let luminance_calc = luminance_calculation(document_node, node_id, 1, "Luminance Calc", true); @@ -938,7 +983,52 @@ pub fn add_properties(document_node: &DocumentNode, node_id: NodeId, _context: & LayoutGroup::Row { widgets } }; - vec![operand("Input", 0), operand("Addend", 1)] + vec![operand("Addend", 1)] +} + +pub fn subtract_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let widgets = number_widget(document_node, node_id, index, name, NumberInput::default(), true); + + LayoutGroup::Row { widgets } + }; + vec![operand("Subtrahend", 1)] +} + +pub fn divide_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let widgets = number_widget(document_node, node_id, index, name, NumberInput::default(), true); + + LayoutGroup::Row { widgets } + }; + vec![operand("Divisor", 1)] +} + +pub fn multiply_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let widgets = number_widget(document_node, node_id, index, name, NumberInput::default(), true); + + LayoutGroup::Row { widgets } + }; + vec![operand("Multiplicand", 1)] +} + +pub fn exponent_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let widgets = number_widget(document_node, node_id, index, name, NumberInput::default(), true); + + LayoutGroup::Row { widgets } + }; + vec![operand("Power", 1)] +} + +pub fn modulo_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let operand = |name: &str, index| { + let widgets = number_widget(document_node, node_id, index, name, NumberInput::default(), true); + + LayoutGroup::Row { widgets } + }; + vec![operand("Modulo", 1)] } pub fn transform_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { diff --git a/node-graph/gcore/src/ops.rs b/node-graph/gcore/src/ops.rs index ac5d12fb..600aed6c 100644 --- a/node-graph/gcore/src/ops.rs +++ b/node-graph/gcore/src/ops.rs @@ -1,8 +1,9 @@ -use core::marker::PhantomData; -use core::ops::{Add, Mul}; - use crate::Node; +use core::marker::PhantomData; +use core::ops::{Add, Div, Mul, Rem, Sub}; +use num_traits::Pow; +// Add #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct AddNode; @@ -30,18 +31,71 @@ where first + second } -pub struct MulParameterNode { +// Subtract +pub struct SubtractParameterNode { second: Second, } -#[node_macro::node_fn(MulParameterNode)] -fn flat_map(first: U, second: T) -> >::Output +#[node_macro::node_fn(SubtractParameterNode)] +fn sub(first: U, second: T) -> >::Output +where + U: Sub, +{ + first - second +} + +// Divide +pub struct DivideParameterNode { + second: Second, +} + +#[node_macro::node_fn(DivideParameterNode)] +fn div(first: U, second: T) -> >::Output +where + U: Div, +{ + first / second +} + +// Multiply +pub struct MultiplyParameterNode { + second: Second, +} + +#[node_macro::node_fn(MultiplyParameterNode)] +fn mul(first: U, second: T) -> >::Output where U: Mul, { first * second } +// Exponent +pub struct ExponentParameterNode { + second: Second, +} + +#[node_macro::node_fn(ExponentParameterNode)] +fn exp(first: U, second: T) -> >::Output +where + U: Pow, +{ + first.pow(second) +} + +// Modulo +pub struct ModuloParameterNode { + second: Second, +} + +#[node_macro::node_fn(ModuloParameterNode)] +fn modulo(first: U, second: T) -> >::Output +where + U: Rem, +{ + first % second +} + #[cfg(feature = "std")] struct SizeOfNode {} diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs index ffc09a70..a9c83406 100644 --- a/node-graph/interpreted-executor/src/node_registry.rs +++ b/node-graph/interpreted-executor/src/node_registry.rs @@ -196,6 +196,46 @@ fn node_registry() -> HashMap, input: &f32, params: [f32]), register_node!(graphene_core::ops::AddParameterNode<_>, input: f32, params: [&f32]), register_node!(graphene_core::ops::AddParameterNode<_>, input: &f32, params: [&f32]), + register_node!(graphene_core::ops::SubtractParameterNode<_>, input: u32, params: [u32]), + register_node!(graphene_core::ops::SubtractParameterNode<_>, input: &u32, params: [u32]), + register_node!(graphene_core::ops::SubtractParameterNode<_>, input: u32, params: [&u32]), + register_node!(graphene_core::ops::SubtractParameterNode<_>, input: &u32, params: [&u32]), + register_node!(graphene_core::ops::SubtractParameterNode<_>, input: f32, params: [f32]), + register_node!(graphene_core::ops::SubtractParameterNode<_>, input: &f32, params: [f32]), + register_node!(graphene_core::ops::SubtractParameterNode<_>, input: f32, params: [&f32]), + register_node!(graphene_core::ops::SubtractParameterNode<_>, input: &f32, params: [&f32]), + register_node!(graphene_core::ops::DivideParameterNode<_>, input: u32, params: [u32]), + register_node!(graphene_core::ops::DivideParameterNode<_>, input: &u32, params: [u32]), + register_node!(graphene_core::ops::DivideParameterNode<_>, input: u32, params: [&u32]), + register_node!(graphene_core::ops::DivideParameterNode<_>, input: &u32, params: [&u32]), + register_node!(graphene_core::ops::DivideParameterNode<_>, input: f32, params: [f32]), + register_node!(graphene_core::ops::DivideParameterNode<_>, input: &f32, params: [f32]), + register_node!(graphene_core::ops::DivideParameterNode<_>, input: f32, params: [&f32]), + register_node!(graphene_core::ops::DivideParameterNode<_>, input: &f32, params: [&f32]), + register_node!(graphene_core::ops::MultiplyParameterNode<_>, input: u32, params: [u32]), + register_node!(graphene_core::ops::MultiplyParameterNode<_>, input: &u32, params: [u32]), + register_node!(graphene_core::ops::MultiplyParameterNode<_>, input: u32, params: [&u32]), + register_node!(graphene_core::ops::MultiplyParameterNode<_>, input: &u32, params: [&u32]), + register_node!(graphene_core::ops::MultiplyParameterNode<_>, input: f32, params: [f32]), + register_node!(graphene_core::ops::MultiplyParameterNode<_>, input: &f32, params: [f32]), + register_node!(graphene_core::ops::MultiplyParameterNode<_>, input: f32, params: [&f32]), + register_node!(graphene_core::ops::MultiplyParameterNode<_>, input: &f32, params: [&f32]), + register_node!(graphene_core::ops::ExponentParameterNode<_>, input: u32, params: [u32]), + register_node!(graphene_core::ops::ExponentParameterNode<_>, input: &u32, params: [u32]), + register_node!(graphene_core::ops::ExponentParameterNode<_>, input: u32, params: [&u32]), + register_node!(graphene_core::ops::ExponentParameterNode<_>, input: &u32, params: [&u32]), + register_node!(graphene_core::ops::ExponentParameterNode<_>, input: f32, params: [f32]), + register_node!(graphene_core::ops::ExponentParameterNode<_>, input: &f32, params: [f32]), + register_node!(graphene_core::ops::ExponentParameterNode<_>, input: f32, params: [&f32]), + register_node!(graphene_core::ops::ExponentParameterNode<_>, input: &f32, params: [&f32]), + register_node!(graphene_core::ops::ModuloParameterNode<_>, input: u32, params: [u32]), + register_node!(graphene_core::ops::ModuloParameterNode<_>, input: &u32, params: [u32]), + register_node!(graphene_core::ops::ModuloParameterNode<_>, input: u32, params: [&u32]), + register_node!(graphene_core::ops::ModuloParameterNode<_>, input: &u32, params: [&u32]), + register_node!(graphene_core::ops::ModuloParameterNode<_>, input: f32, params: [f32]), + register_node!(graphene_core::ops::ModuloParameterNode<_>, input: &f32, params: [f32]), + register_node!(graphene_core::ops::ModuloParameterNode<_>, input: f32, params: [&f32]), + register_node!(graphene_core::ops::ModuloParameterNode<_>, input: &f32, params: [&f32]), register_node!(graphene_core::ops::SomeNode, input: WasmEditorApi, params: []), async_node!(graphene_core::ops::IntoNode<_, ImageFrame>, input: ImageFrame, output: ImageFrame, params: []), async_node!(graphene_core::ops::IntoNode<_, ImageFrame>, input: ImageFrame, output: ImageFrame, params: []),