mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Add "Blend" node (#1024)
* Add Blend node * Add more implementations Currently, known buggy implementations: * Color Burn * Saturation Opacity is currently achieved by linear interpolation, this will be changed as soon as all filters are implemented. * Add more implementations Currently, known incorrect implementations: * Color Burn * Saturation Not yet Tested: * Linear Burn * Linear Dodge * Vivid Light * Linear Light * Pin Light * Hard Mix * Subtract * Divide Opacity is currently achieved by linear interpolation, this will be changed as soon as all filters are implemented. * Cleanup * Removed Unused Code * Fixed Clamping Issue * Fixed Inverted Opacity * Moved Opacity Calculation from individual Blend Functions into 'blend_node' function * Fix 'Color Burn' blend mode Currently, known incorrect implementations: * Saturation Not yet Tested: * Linear Burn * Darker Color * Linear Dodge * Lighter Color * Vivid Light * Linear Light * Pin Light * Hard Mix * Subtract * Divide Opacity is currently achieved by linear interpolation, this will be changed as soon as all filters are implemented. * Fix 'Saturation' blend mode Currently, known incorrect implementations: * None :D Not yet Tested: * Linear Burn * Darker Color * Linear Dodge * Lighter Color * Vivid Light * Linear Light * Pin Light * Hard Mix * Subtract * Divide Opacity is currently achieved by linear interpolation, this will be changed as soon as all filters are implemented. * Final Cleanups * Add proper Inputs * cargo fmt * Add test for doubling number * Display implementation for ProtoNetwork * Switch top and bottom * Add input types for blend image node * Fix test --------- Co-authored-by: 0hypercube <0hypercube@gmail.com> Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
@@ -115,4 +115,49 @@ mod tests {
|
||||
let val = *dyn_any::downcast::<u32>(result).unwrap();
|
||||
assert_eq!(val, 33_u32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_number() {
|
||||
use graph_craft::document::*;
|
||||
|
||||
use graph_craft::*;
|
||||
|
||||
let network = NodeNetwork {
|
||||
inputs: vec![0],
|
||||
outputs: vec![NodeOutput::new(1, 0)],
|
||||
nodes: [
|
||||
// Simple identity node taking a number as input from ouside the graph
|
||||
(
|
||||
0,
|
||||
DocumentNode {
|
||||
name: "id".into(),
|
||||
inputs: vec![NodeInput::Network(concrete!(u32))],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")),
|
||||
metadata: DocumentNodeMetadata::default(),
|
||||
},
|
||||
),
|
||||
// An add node adding the result of the id node to its self
|
||||
(
|
||||
1,
|
||||
DocumentNode {
|
||||
name: "Add".into(),
|
||||
inputs: vec![NodeInput::node(0, 0), NodeInput::node(0, 0)],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::AddParameterNode<_>")),
|
||||
metadata: DocumentNodeMetadata::default(),
|
||||
},
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
use crate::executor::DynamicExecutor;
|
||||
use graph_craft::executor::{Compiler, Executor};
|
||||
|
||||
let compiler = Compiler {};
|
||||
let protograph = compiler.compile_single(network, true).expect("Graph should be generated");
|
||||
|
||||
let exec = DynamicExecutor::new(protograph).map(|e| panic!("The network should not type check: {:#?}", e)).unwrap_err();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,25 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
|
||||
// Filters
|
||||
raster_node!(graphene_core::raster::LuminanceNode<_>, params: [LuminanceCalculation]),
|
||||
raster_node!(graphene_core::raster::LevelsNode<_, _, _, _, _>, params: [f64, f64, f64, f64, f64]),
|
||||
(
|
||||
NodeIdentifier::new("graphene_core::raster::BlendNode<_, _, _, _>"),
|
||||
|args| {
|
||||
use graphene_core::Node;
|
||||
let image: DowncastBothNode<(), Image> = DowncastBothNode::new(args[0]);
|
||||
let blend_mode: DowncastBothNode<(), BlendMode> = DowncastBothNode::new(args[1]);
|
||||
let opacity: DowncastBothNode<(), f64> = DowncastBothNode::new(args[2]);
|
||||
let blend_node = graphene_core::raster::BlendNode::new(ClonedNode::new(blend_mode.eval(())), ClonedNode::new(opacity.eval(())));
|
||||
let node = graphene_std::raster::BlendImageNode::new(image, ValueNode::new(blend_node));
|
||||
let _ = &node as &dyn for<'i> Node<'i, Image, Output = Image>;
|
||||
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![(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::HueSaturationNode<_, _, _>, params: [f64, f64, f64]),
|
||||
raster_node!(graphene_core::raster::InvertRGBNode, params: []),
|
||||
|
||||
Reference in New Issue
Block a user