diff --git a/editor/src/messages/portfolio/document/node_graph/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_properties.rs index d9279908..3798c1e8 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -2132,11 +2132,22 @@ pub fn stroke_properties(document_node: &DocumentNode, node_id: NodeId, _context let color = color_widget(document_node, node_id, color_index, "Color", ColorButton::default(), true); let weight = number_widget(document_node, node_id, weight_index, "Weight", NumberInput::default().unit("px").min(0.), true); + + let dash_lengths_val = match &document_node.inputs[dash_lengths_index].as_value() { + Some(TaggedValue::VecF64(x)) => x, + _ => &vec![], + }; let dash_lengths = vec_f64_input(document_node, node_id, dash_lengths_index, "Dash Lengths", TextInput::default().centered(true), true); - let dash_offset = number_widget(document_node, node_id, dash_offset_index, "Dash Offset", NumberInput::default().unit("px").min(0.), true); + let number_input = NumberInput::default().unit("px").disabled(dash_lengths_val.is_empty()); + let dash_offset = number_widget(document_node, node_id, dash_offset_index, "Dash Offset", number_input, true); let line_cap = line_cap_widget(document_node, node_id, line_cap_index, "Line Cap", true); let line_join = line_join_widget(document_node, node_id, line_join_index, "Line Join", true); - let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", NumberInput::default().min(0.), true); + let line_join_val = match &document_node.inputs[line_join_index].as_value() { + Some(TaggedValue::LineJoin(x)) => x, + _ => &LineJoin::Miter, + }; + let number_input = NumberInput::default().min(0.).disabled(line_join_val != &LineJoin::Miter); + let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", number_input, true); vec![ color, diff --git a/node-graph/gcore/src/graphic_element/renderer.rs b/node-graph/gcore/src/graphic_element/renderer.rs index 6c1c3d65..fbede2e8 100644 --- a/node-graph/gcore/src/graphic_element/renderer.rs +++ b/node-graph/gcore/src/graphic_element/renderer.rs @@ -327,8 +327,10 @@ impl GraphicElementRendered for VectorData { fn bounding_box(&self, transform: DAffine2) -> Option<[DVec2; 2]> { let stroke_width = self.style.stroke().map(|s| s.weight()).unwrap_or_default(); + let miter_limit = self.style.stroke().map(|s| s.line_join_miter_limit).unwrap_or(1.); let scale = transform.decompose_scale(); - let offset = DVec2::splat(stroke_width * scale.x.max(scale.y) / 2.); + // We use the full line width here to account for different styles of line caps + let offset = DVec2::splat(stroke_width * scale.x.max(scale.y) * miter_limit); self.bounding_box_with_transform(transform * self.transform).map(|[a, b]| [a - offset, b + offset]) } @@ -349,8 +351,7 @@ impl GraphicElementRendered for VectorData { use crate::vector::style::GradientType; use vello::peniko; - let multiplied_transform = transform * self.transform; - let transformed_bounds = self.bounding_box_with_transform(multiplied_transform).unwrap_or_default(); + let transformed_bounds = GraphicElementRendered::bounding_box(self, transform).unwrap_or_default(); let mut layer = false; if self.alpha_blending.opacity < 1. || self.alpha_blending.blend_mode != BlendMode::default() { @@ -424,10 +425,26 @@ impl GraphicElementRendered for VectorData { Some(color) => peniko::Color::rgba(color.r() as f64, color.g() as f64, color.b() as f64, color.a() as f64), None => peniko::Color::TRANSPARENT, }; + use crate::vector::style::{LineCap, LineJoin}; + use vello::kurbo::{Cap, Join}; + let cap = match stroke.line_cap { + LineCap::Butt => Cap::Butt, + LineCap::Round => Cap::Round, + LineCap::Square => Cap::Square, + }; + let join = match stroke.line_join { + LineJoin::Miter => Join::Miter, + LineJoin::Bevel => Join::Bevel, + LineJoin::Round => Join::Round, + }; let stroke = kurbo::Stroke { width: stroke.weight, miter_limit: stroke.line_join_miter_limit, - ..Default::default() + join, + start_cap: cap, + end_cap: cap, + dash_pattern: stroke.dash_lengths.into(), + dash_offset: stroke.dash_offset, }; if stroke.width > 0. { scene.stroke(&stroke, kurbo_transform, color, None, &path);