From a244cc13d06afbde73df634c1b39d2604b13bd17 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Sat, 22 Aug 2026 14:32:15 +0000 Subject: [PATCH] Convert the blending family to attribute kernels --- node-graph/nodes/blending/src/lib.rs | 248 +++------------------------ 1 file changed, 22 insertions(+), 226 deletions(-) diff --git a/node-graph/nodes/blending/src/lib.rs b/node-graph/nodes/blending/src/lib.rs index fea3aa5ad9..609b1333ef 100644 --- a/node-graph/nodes/blending/src/lib.rs +++ b/node-graph/nodes/blending/src/lib.rs @@ -1,223 +1,28 @@ -use core_types::list::List; +use core_types::attribute::{Attr, BlendMode as BlendModeAttr, ClippingMask, Opacity, OpacityFill}; use core_types::registry::types::Percentage; -use core_types::{ATTR_BLEND_MODE, ATTR_CLIPPING_MASK, ATTR_OPACITY, ATTR_OPACITY_FILL, BlendMode, Color, Ctx}; -use graphic_types::Graphic; -use graphic_types::Vector; -use graphic_types::raster_types::{CPU, Raster}; -use vector_types::GradientStops; +use core_types::{BlendMode, Ctx}; -pub(crate) trait MultiplyAlpha { - fn multiply_alpha(&mut self, factor: f64); -} - -impl MultiplyAlpha for Color { - fn multiply_alpha(&mut self, factor: f64) { - *self = Color::from_rgbaf32_unchecked(self.r(), self.g(), self.b(), (self.a() * factor as f32).clamp(0., 1.)) - } -} - -fn multiply_list_attribute(list: &mut List, key: &str, factor: f64) { - if let Some(values) = list.iter_attribute_values_mut::(key) { - for v in values { - *v *= factor; - } - } else { - for v in list.iter_attribute_values_mut_or_default::(key) { - *v = factor; - } - } -} - -impl MultiplyAlpha for List { - fn multiply_alpha(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY, factor); - } -} -impl MultiplyAlpha for List { - fn multiply_alpha(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY, factor); - } -} -impl MultiplyAlpha for List> { - fn multiply_alpha(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY, factor); - } -} -impl MultiplyAlpha for List { - fn multiply_alpha(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY, factor); - } -} -impl MultiplyAlpha for List { - fn multiply_alpha(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY, factor); - } -} -impl MultiplyAlpha for List { - fn multiply_alpha(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY, factor); - } -} - -pub(crate) trait MultiplyFill { - fn multiply_fill(&mut self, factor: f64); -} -impl MultiplyFill for Color { - fn multiply_fill(&mut self, factor: f64) { - *self = Color::from_rgbaf32_unchecked(self.r(), self.g(), self.b(), (self.a() * factor as f32).clamp(0., 1.)) - } -} -impl MultiplyFill for List { - fn multiply_fill(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY_FILL, factor); - } -} -impl MultiplyFill for List { - fn multiply_fill(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY_FILL, factor); - } -} -impl MultiplyFill for List> { - fn multiply_fill(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY_FILL, factor); - } -} -impl MultiplyFill for List { - fn multiply_fill(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY_FILL, factor); - } -} -impl MultiplyFill for List { - fn multiply_fill(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY_FILL, factor); - } -} -impl MultiplyFill for List { - fn multiply_fill(&mut self, factor: f64) { - multiply_list_attribute(self, ATTR_OPACITY_FILL, factor); - } -} - -trait SetBlendMode { - fn set_blend_mode(&mut self, blend_mode: BlendMode); -} - -fn set_list_blend_mode(list: &mut List, blend_mode: BlendMode) { - for v in list.iter_attribute_values_mut_or_default::(ATTR_BLEND_MODE) { - *v = blend_mode; - } -} - -impl SetBlendMode for List { - fn set_blend_mode(&mut self, blend_mode: BlendMode) { - set_list_blend_mode(self, blend_mode); - } -} -impl SetBlendMode for List { - fn set_blend_mode(&mut self, blend_mode: BlendMode) { - set_list_blend_mode(self, blend_mode); - } -} -impl SetBlendMode for List> { - fn set_blend_mode(&mut self, blend_mode: BlendMode) { - set_list_blend_mode(self, blend_mode); - } -} -impl SetBlendMode for List { - fn set_blend_mode(&mut self, blend_mode: BlendMode) { - set_list_blend_mode(self, blend_mode); - } -} -impl SetBlendMode for List { - fn set_blend_mode(&mut self, blend_mode: BlendMode) { - set_list_blend_mode(self, blend_mode); - } -} -impl SetBlendMode for List { - fn set_blend_mode(&mut self, blend_mode: BlendMode) { - set_list_blend_mode(self, blend_mode); - } -} - -trait SetClip { - fn set_clip(&mut self, clip: bool); -} - -fn set_list_clip(list: &mut List, clip: bool) { - for v in list.iter_attribute_values_mut_or_default::(ATTR_CLIPPING_MASK) { - *v = clip; - } -} - -impl SetClip for List { - fn set_clip(&mut self, clip: bool) { - set_list_clip(self, clip); - } -} -impl SetClip for List { - fn set_clip(&mut self, clip: bool) { - set_list_clip(self, clip); - } -} -impl SetClip for List> { - fn set_clip(&mut self, clip: bool) { - set_list_clip(self, clip); - } -} -impl SetClip for List { - fn set_clip(&mut self, clip: bool) { - set_list_clip(self, clip); - } -} -impl SetClip for List { - fn set_clip(&mut self, clip: bool) { - set_list_clip(self, clip); - } -} -impl SetClip for List { - fn set_clip(&mut self, clip: bool) { - set_list_clip(self, clip); - } -} /// Applies the blend mode to the input graphics. Setting this allows for customizing how overlapping content is composited together. #[node_macro::node(category("Blending"))] -fn blend_mode( +fn blend_mode( _: impl Ctx, /// The layer stack that will be composited when rendering. - #[implementations( - List, - List, - List>, - List, - List, - List, - )] - mut content: T, + (element, _content_blend_mode): (T, Attr), /// The choice of equation that controls how brightness and color blends between overlapping pixels. blend_mode: BlendMode, -) -> T { - // TODO: Find a way to make this apply once to the list's parent (i.e. its item in its parent List or Item) rather than applying to each item in its own list, which produces the undesired result - content.set_blend_mode(blend_mode); - content +) -> (T, Attr) { + (element, Attr(blend_mode)) } /// Modifies the opacity and/or fill of the input graphics by multiplying the existing values by these percentages. /// Opacity affects the transparency of the content (together with anything above which is clipped to it). /// Fill affects the transparency of the content itself, independent of any content clipped to it. #[node_macro::node(category("Blending"))] -fn opacity( +fn opacity( _: impl Ctx, /// The layer stack that will be composited when rendering. - #[implementations( - List, - List, - List>, - List, - List, - List, - )] - mut content: T, + (element, content_opacity, content_fill): (T, Attr, Attr), /// Whether the *Opacity* property is enabled, multiplying the existing opacity by the chosen percentage. #[widget(ParsedWidgetOverride::Hidden)] #[default(true)] @@ -235,35 +40,26 @@ fn opacity( #[widget(ParsedWidgetOverride::Custom = "optional_percentage")] #[default(100.)] fill: Percentage, -) -> T { - // TODO: Find a way to make this apply once to the list's parent (i.e. its item in its parent List or Item) rather than applying to each item in its own list, which produces the undesired result - if has_opacity { - content.multiply_alpha(opacity / 100.); - } - if has_fill { - content.multiply_fill(fill / 100.); - } - content +) -> (T, Attr, Attr) { + let opacity = match has_opacity { + true => *content_opacity * (opacity / 100.), + false => *content_opacity, + }; + let fill = match has_fill { + true => *content_fill * (fill / 100.), + false => *content_fill, + }; + (element, Attr(opacity), Attr(fill)) } /// Sets whether the input graphics inherit the alpha of the content beneath them, "clipping" them to that content. #[node_macro::node(category("Blending"))] -fn clipping_mask( +fn clipping_mask( _: impl Ctx, /// The layer stack that will be composited when rendering. - #[implementations( - List, - List, - List>, - List, - List, - List, - )] - mut content: T, + (element, _content_clip): (T, Attr), /// Whether the content inherits the alpha of the content beneath it. clip: bool, -) -> T { - // TODO: Find a way to make this apply once to the list's parent (i.e. its item in its parent List or Item) rather than applying to each item in its own list, which produces the undesired result - content.set_clip(clip); - content +) -> (T, Attr) { + (element, Attr(clip)) }