mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 13:30:48 +00: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:
parent
48dcc2774b
commit
8fe19063c1
10 changed files with 534 additions and 10 deletions
|
@ -2,7 +2,7 @@ pub use dyn_any::StaticType;
|
|||
use dyn_any::{DynAny, Upcast};
|
||||
use dyn_clone::DynClone;
|
||||
pub use glam::{DAffine2, DVec2};
|
||||
use graphene_core::raster::LuminanceCalculation;
|
||||
use graphene_core::raster::{BlendMode, LuminanceCalculation};
|
||||
use graphene_core::{Node, Type};
|
||||
use std::hash::Hash;
|
||||
pub use std::sync::Arc;
|
||||
|
@ -29,6 +29,7 @@ pub enum TaggedValue {
|
|||
Color(graphene_core::raster::color::Color),
|
||||
Subpath(graphene_core::vector::subpath::Subpath),
|
||||
RcSubpath(Arc<graphene_core::vector::subpath::Subpath>),
|
||||
BlendMode(BlendMode),
|
||||
LuminanceCalculation(LuminanceCalculation),
|
||||
ImaginateSamplingMethod(ImaginateSamplingMethod),
|
||||
ImaginateMaskStartingFill(ImaginateMaskStartingFill),
|
||||
|
@ -94,24 +95,28 @@ impl Hash for TaggedValue {
|
|||
14.hash(state);
|
||||
s.hash(state)
|
||||
}
|
||||
Self::LuminanceCalculation(l) => {
|
||||
Self::BlendMode(b) => {
|
||||
15.hash(state);
|
||||
b.hash(state)
|
||||
}
|
||||
Self::LuminanceCalculation(l) => {
|
||||
16.hash(state);
|
||||
l.hash(state)
|
||||
}
|
||||
Self::ImaginateSamplingMethod(m) => {
|
||||
16.hash(state);
|
||||
17.hash(state);
|
||||
m.hash(state)
|
||||
}
|
||||
Self::ImaginateMaskStartingFill(f) => {
|
||||
17.hash(state);
|
||||
18.hash(state);
|
||||
f.hash(state)
|
||||
}
|
||||
Self::ImaginateStatus(s) => {
|
||||
18.hash(state);
|
||||
19.hash(state);
|
||||
s.hash(state)
|
||||
}
|
||||
Self::LayerPath(p) => {
|
||||
19.hash(state);
|
||||
20.hash(state);
|
||||
p.hash(state)
|
||||
}
|
||||
Self::ImageFrame(i) => {
|
||||
|
@ -142,6 +147,7 @@ impl<'a> TaggedValue {
|
|||
TaggedValue::Color(x) => Box::new(x),
|
||||
TaggedValue::Subpath(x) => Box::new(x),
|
||||
TaggedValue::RcSubpath(x) => Box::new(x),
|
||||
TaggedValue::BlendMode(x) => Box::new(x),
|
||||
TaggedValue::LuminanceCalculation(x) => Box::new(x),
|
||||
TaggedValue::ImaginateSamplingMethod(x) => Box::new(x),
|
||||
TaggedValue::ImaginateMaskStartingFill(x) => Box::new(x),
|
||||
|
@ -168,6 +174,7 @@ impl<'a> TaggedValue {
|
|||
TaggedValue::Color(_) => concrete!(graphene_core::raster::Color),
|
||||
TaggedValue::Subpath(_) => concrete!(graphene_core::vector::subpath::Subpath),
|
||||
TaggedValue::RcSubpath(_) => concrete!(Arc<graphene_core::vector::subpath::Subpath>),
|
||||
TaggedValue::BlendMode(_) => concrete!(BlendMode),
|
||||
TaggedValue::ImaginateSamplingMethod(_) => concrete!(ImaginateSamplingMethod),
|
||||
TaggedValue::ImaginateMaskStartingFill(_) => concrete!(ImaginateMaskStartingFill),
|
||||
TaggedValue::ImaginateStatus(_) => concrete!(ImaginateStatus),
|
||||
|
|
|
@ -23,6 +23,51 @@ pub struct ProtoNetwork {
|
|||
pub nodes: Vec<(NodeId, ProtoNode)>,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for ProtoNetwork {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.write_str("Proto Network with nodes: ")?;
|
||||
fn write_node(f: &mut core::fmt::Formatter<'_>, network: &ProtoNetwork, id: NodeId, indent: usize) -> core::fmt::Result {
|
||||
f.write_str(&"\t".repeat(indent))?;
|
||||
let Some((_, node)) = network.nodes.iter().find(|(node_id, _)|*node_id == id) else{
|
||||
return f.write_str("{{Unknown Node}}");
|
||||
};
|
||||
f.write_str("Node: ")?;
|
||||
f.write_str(&node.identifier.name)?;
|
||||
|
||||
f.write_str("\n")?;
|
||||
f.write_str(&"\t".repeat(indent))?;
|
||||
f.write_str("{\n")?;
|
||||
|
||||
f.write_str(&"\t".repeat(indent + 1))?;
|
||||
f.write_str("Primary input: ")?;
|
||||
match &node.input {
|
||||
ProtoNodeInput::None => f.write_str("None")?,
|
||||
ProtoNodeInput::Network(ty) => f.write_fmt(format_args!("Network (type = {:?})", ty))?,
|
||||
ProtoNodeInput::Node(_) => f.write_str("Node")?,
|
||||
}
|
||||
f.write_str("\n")?;
|
||||
|
||||
match &node.construction_args {
|
||||
ConstructionArgs::Value(value) => {
|
||||
f.write_str(&"\t".repeat(indent + 1))?;
|
||||
f.write_fmt(format_args!("Value construction argument: {value:?}"))?
|
||||
}
|
||||
ConstructionArgs::Nodes(nodes) => {
|
||||
for id in nodes {
|
||||
write_node(f, network, *id, indent + 1)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
f.write_str(&"\t".repeat(indent))?;
|
||||
f.write_str("}\n")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let id = self.output;
|
||||
write_node(f, self, id, 0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ConstructionArgs {
|
||||
Value(value::TaggedValue),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue