Skip to content

Commit

Permalink
Add the apply style trait for generalised application of styles
Browse files Browse the repository at this point in the history
  • Loading branch information
0HyperCube committed Oct 16, 2024
1 parent 9f7b393 commit c6e5f38
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 16 deletions.
10 changes: 10 additions & 0 deletions node-graph/gcore/src/graphic_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ impl GraphicGroup {
}
}

impl crate::vector::ApplyStyle for GraphicGroup {
fn apply(&mut self, mut modify_fn: impl FnMut(&mut crate::vector::PathStyle, DAffine2)) {
// The style is applied only to direct children (a bit unintuitive perhaps)
for (direct_child, _) in self.elements.iter_mut() {
let GraphicElement::VectorData(direct_child) = direct_child else { continue };
modify_fn(&mut direct_child.style, self.transform * direct_child.transform);
}
}
}

/// The possible forms of graphical content held in a Vec by the `elements` field of [`GraphicElement`].
/// Can be another recursively nested [`GraphicGroup`], a [`VectorData`] shape, an [`ImageFrame`], or an [`Artboard`].
#[derive(Clone, Debug, Hash, PartialEq, DynAny)]
Expand Down
90 changes: 74 additions & 16 deletions node-graph/gcore/src/vector/vector_nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,36 @@ async fn assign_colors<F: 'n + Send, T: VectorIterMut>(
input
}

/// A trait to allow the application of the path style (which allows the fill and stroke node to support either GraphicGroup or VectorData)
pub trait ApplyStyle {
fn apply(&mut self, modify_fn: impl FnMut(&mut crate::vector::PathStyle, DAffine2)) {}
}

impl ApplyStyle for VectorData {
fn apply(&mut self, mut modify_fn: impl FnMut(&mut crate::vector::PathStyle, DAffine2)) {
// Simply modify the only path style available here.
modify_fn(&mut self.style, self.transform)
}
}

#[node_macro::node(category("Vector: Style"), path(graphene_core::vector))]
async fn fill<F: 'n + Send, T: Into<Fill> + 'n + Send>(
async fn fill<F: 'n + Send, FillTy: Into<Fill> + 'n + Send, TargetTy: ApplyStyle + 'n + Send>(
#[implementations(
(),
(),
(),
(),
(),
(),
(),
(),
Footprint,
Footprint,
Footprint,
Footprint,
Footprint,
Footprint,
Footprint,
Footprint,
)]
footprint: F,
Expand All @@ -96,9 +119,20 @@ async fn fill<F: 'n + Send, T: Into<Fill> + 'n + Send>(
() -> VectorData,
() -> VectorData,
() -> VectorData,
() -> GraphicGroup,
() -> GraphicGroup,
() -> GraphicGroup,
() -> GraphicGroup,
Footprint -> VectorData,
Footprint -> VectorData,
Footprint -> VectorData,
Footprint -> VectorData,
Footprint -> GraphicGroup,
Footprint -> GraphicGroup,
Footprint -> GraphicGroup,
Footprint -> GraphicGroup,
)]
vector_data: impl Node<F, Output = VectorData>,
vector_data: impl Node<F, Output = TargetTy>,
#[implementations(
Fill,
Option<Color>,
Expand All @@ -108,59 +142,83 @@ async fn fill<F: 'n + Send, T: Into<Fill> + 'n + Send>(
Option<Color>,
Color,
Gradient,
Fill,
Option<Color>,
Color,
Gradient,
Fill,
Option<Color>,
Color,
Gradient,
)]
#[default(Color::BLACK)]
fill: T,
fill: FillTy,
_backup_color: Option<Color>,
_backup_gradient: Gradient,
) -> VectorData {
let mut vector_data = vector_data.eval(footprint).await;
vector_data.style.set_fill(fill.into());
) -> TargetTy {
let mut target = vector_data.eval(footprint).await;
let fill: Fill = fill.into();
target.apply(|style, _| style.set_fill(fill.clone()));

vector_data
target
}

#[node_macro::node(category("Vector: Style"), path(graphene_core::vector))]
async fn stroke<F: 'n + Send, T: Into<Option<Color>> + 'n + Send>(
async fn stroke<F: 'n + Send, ColourTy: Into<Option<Color>> + 'n + Send, TargetTy: ApplyStyle + 'n + Send>(
#[implementations(
(),
(),
(),
(),
Footprint,
Footprint,
Footprint,
Footprint,
)]
footprint: F,
#[implementations(
() -> VectorData,
() -> VectorData,
() -> GraphicGroup,
() -> GraphicGroup,
Footprint -> VectorData,
Footprint -> VectorData,
Footprint -> GraphicGroup,
Footprint -> GraphicGroup,
)]
vector_data: impl Node<F, Output = VectorData>,
vector_data: impl Node<F, Output = TargetTy>,
#[implementations(
Option<Color>,
Color,
Option<Color>,
Color,
Option<Color>,
Color,
Option<Color>,
Color,
)]
#[default(Color::BLACK)]
color: T,
color: ColourTy,
#[default(2.)] weight: f64,
dash_lengths: Vec<f64>,
dash_offset: f64,
line_cap: crate::vector::style::LineCap,
line_join: LineJoin,
#[default(4.)] miter_limit: f64,
) -> VectorData {
let mut vector_data = vector_data.eval(footprint).await;
vector_data.style.set_stroke(Stroke {
) -> TargetTy {
let mut target = vector_data.eval(footprint).await;
let stroke = Stroke {
color: color.into(),
weight,
dash_lengths,
dash_offset,
line_cap,
line_join,
line_join_miter_limit: miter_limit,
transform: vector_data.transform,
});
vector_data
transform: DAffine2::IDENTITY,
};
target.apply(|style, transform| style.set_stroke(Stroke { transform, ..stroke.clone() }));
target
}

#[node_macro::node(category("Vector"), path(graphene_core::vector))]
Expand Down

0 comments on commit c6e5f38

Please sign in to comment.