From da752e5324986051a396ef6f1821ebc424369dd3 Mon Sep 17 00:00:00 2001 From: Nitish Choudhary <86357181+Nitish-bot@users.noreply.github.com> Date: Wed, 5 Feb 2025 15:55:07 +0530 Subject: [PATCH] Make primitive shape tools no longer draw transformed unit shapes (#2236) * Line tool pt.1 * Line tool complete * Fix hints * Rectangle tool * Fix bad naming * Ellipse tool but cant get id * Fix line tool * Polygon tool * Revert unrequested Line tool keybind change; code review cleanup --------- Co-authored-by: Keavon Chambers --- .../graph_modification_utils.rs | 20 ++++++++ .../tool/tool_messages/ellipse_tool.rs | 17 ++++++- .../messages/tool/tool_messages/line_tool.rs | 51 ++++++++++--------- .../tool/tool_messages/polygon_tool.rs | 45 +++++++++++++++- .../tool/tool_messages/rectangle_tool.rs | 18 ++++++- 5 files changed, 122 insertions(+), 29 deletions(-) diff --git a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs index dfb8694e..18c6c0b4 100644 --- a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs +++ b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs @@ -223,6 +223,26 @@ pub fn get_fill_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkIn NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Fill") } +pub fn get_ellipse_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option { + NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Ellipse") +} + +pub fn get_line_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option { + NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Line") +} + +pub fn get_polygon_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option { + NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Regular Polygon") +} + +pub fn get_rectangle_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option { + NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Rectangle") +} + +pub fn get_star_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option { + NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Star") +} + pub fn get_text_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option { NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Text") } diff --git a/editor/src/messages/tool/tool_messages/ellipse_tool.rs b/editor/src/messages/tool/tool_messages/ellipse_tool.rs index b38fe917..ecbd2cbb 100644 --- a/editor/src/messages/tool/tool_messages/ellipse_tool.rs +++ b/editor/src/messages/tool/tool_messages/ellipse_tool.rs @@ -3,6 +3,7 @@ use crate::consts::DEFAULT_STROKE_WIDTH; use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn; use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; +use crate::messages::portfolio::document::utility_types::network_interface::InputConnector; use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::graph_modification_utils; @@ -220,12 +221,26 @@ impl Fsm for EllipseToolFsmState { (EllipseToolFsmState::Drawing, EllipseToolMessage::PointerMove { center, lock_ratio }) => { if let Some([start, end]) = shape_data.calculate_points(document, input, center, lock_ratio) { if let Some(layer) = shape_data.layer { + let Some(node_id) = graph_modification_utils::get_ellipse_id(layer, &document.network_interface) else { + return self; + }; + + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, 1), + input: NodeInput::value(TaggedValue::F64(((start.x - end.x) / 2.).abs()), false), + }); + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, 2), + input: NodeInput::value(TaggedValue::F64(((start.y - end.y) / 2.).abs()), false), + }); responses.add(GraphOperationMessage::TransformSet { layer, - transform: DAffine2::from_scale_angle_translation((end - start).abs(), 0., (start + end) / 2.), + transform: DAffine2::from_translation((start + end) / 2.), transform_in: TransformIn::Viewport, skip_rerender: false, }); + + responses.add(NodeGraphMessage::RunDocumentGraph); } } diff --git a/editor/src/messages/tool/tool_messages/line_tool.rs b/editor/src/messages/tool/tool_messages/line_tool.rs index e61eee38..e9aa0836 100644 --- a/editor/src/messages/tool/tool_messages/line_tool.rs +++ b/editor/src/messages/tool/tool_messages/line_tool.rs @@ -1,9 +1,8 @@ use super::tool_prelude::*; use crate::consts::{DEFAULT_STROKE_WIDTH, LINE_ROTATE_SNAP_ANGLE}; -use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn; use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; -use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; +use crate::messages::portfolio::document::utility_types::{document_metadata::LayerNodeIdentifier, network_interface::InputConnector}; use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::graph_modification_utils; @@ -179,23 +178,24 @@ impl Fsm for LineToolFsmState { let node_type = resolve_document_node_type("Line").expect("Line node does not exist"); let node = node_type.node_template_input_override([ None, - Some(NodeInput::value(TaggedValue::DVec2(DVec2::ZERO), false)), - Some(NodeInput::value(TaggedValue::DVec2(DVec2::X), false)), + Some(NodeInput::value( + TaggedValue::DVec2(document.metadata().document_to_viewport.transform_point2(tool_data.drag_start)), + false, + )), + Some(NodeInput::value( + TaggedValue::DVec2(document.metadata().document_to_viewport.transform_point2(tool_data.drag_start)), + false, + )), ]); let nodes = vec![(NodeId(0), node)]; let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, document.new_layer_bounding_artboard(input), responses); responses.add(Message::StartBuffer); - responses.add(GraphOperationMessage::TransformSet { - layer, - transform: DAffine2::from_scale_angle_translation(DVec2::ONE, 0., input.mouse.position), - transform_in: TransformIn::Viewport, - skip_rerender: false, - }); + tool_options.stroke.apply_stroke(tool_options.line_weight, layer, responses); - tool_data.layer = Some(layer); tool_data.layer = Some(layer); + tool_data.angle = 0.; tool_data.weight = tool_options.line_weight; LineToolFsmState::Drawing @@ -206,7 +206,7 @@ impl Fsm for LineToolFsmState { let keyboard = &input.keyboard; let ignore = if let Some(layer) = tool_data.layer { vec![layer] } else { vec![] }; let snap_data = SnapData::ignore(document, input, &ignore); - responses.add(generate_transform(tool_data, snap_data, keyboard.key(lock_angle), keyboard.key(snap_angle), keyboard.key(center))); + generate_line(tool_data, snap_data, keyboard.key(lock_angle), keyboard.key(snap_angle), keyboard.key(center), responses); // Auto-panning let messages = [ @@ -287,7 +287,7 @@ impl Fsm for LineToolFsmState { } } -fn generate_transform(tool_data: &mut LineToolData, snap_data: SnapData, lock_angle: bool, snap_angle: bool, center: bool) -> Message { +fn generate_line(tool_data: &mut LineToolData, snap_data: SnapData, lock_angle: bool, snap_angle: bool, center: bool, responses: &mut VecDeque) { let document_to_viewport = snap_data.document.metadata().document_to_viewport; let mut document_points = [tool_data.drag_start, document_to_viewport.inverse().transform_point2(tool_data.drag_current)]; @@ -347,17 +347,18 @@ fn generate_transform(tool_data: &mut LineToolData, snap_data: SnapData, lock_an snap.update_indicator(snapped); } - // Used for keeping the same angle next frame - tool_data.angle = -(document_points[1] - document_points[0]).angle_to(DVec2::X); + let Some(node_id) = graph_modification_utils::get_line_id(tool_data.layer.unwrap(), &snap_data.document.network_interface) else { + return; + }; - let viewport_points = [document_to_viewport.transform_point2(document_points[0]), document_to_viewport.transform_point2(document_points[1])]; - let line_length = (viewport_points[1] - viewport_points[0]).length(); - let angle = -(viewport_points[1] - viewport_points[0]).angle_to(DVec2::X); - GraphOperationMessage::TransformSet { - layer: tool_data.layer.unwrap(), - transform: glam::DAffine2::from_scale_angle_translation(DVec2::new(line_length, 1.), angle, viewport_points[0]), - transform_in: TransformIn::Viewport, - skip_rerender: false, - } - .into() + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, 1), + input: NodeInput::value(TaggedValue::DVec2(document_points[0]), false), + }); + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, 2), + input: NodeInput::value(TaggedValue::DVec2(document_points[1]), false), + }); + + responses.add(NodeGraphMessage::RunDocumentGraph); } diff --git a/editor/src/messages/tool/tool_messages/polygon_tool.rs b/editor/src/messages/tool/tool_messages/polygon_tool.rs index cb3ba2d6..1d27f383 100644 --- a/editor/src/messages/tool/tool_messages/polygon_tool.rs +++ b/editor/src/messages/tool/tool_messages/polygon_tool.rs @@ -282,12 +282,55 @@ impl Fsm for PolygonToolFsmState { // TODO: make the scale impact the polygon/star node - we need to determine how to allow the polygon node to make irregular shapes update_radius_sign(end, start, layer, document, responses); + + let dimensions = (start - end).abs(); + let mut scale = DVec2::ONE; + let radius: f64; + + // We keep the smaller dimension's scale at 1 and scale the other dimension accordingly + if dimensions.x > dimensions.y { + scale.x = dimensions.x / dimensions.y; + radius = dimensions.y / 2.; + } else { + scale.y = dimensions.y / dimensions.x; + radius = dimensions.x / 2.; + } + + match tool_options.polygon_type { + PolygonType::Convex => { + let Some(node_id) = graph_modification_utils::get_polygon_id(layer, &document.network_interface) else { + return self; + }; + + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, 2), + input: NodeInput::value(TaggedValue::F64(radius), false), + }); + } + PolygonType::Star => { + let Some(node_id) = graph_modification_utils::get_star_id(layer, &document.network_interface) else { + return self; + }; + + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, 2), + input: NodeInput::value(TaggedValue::F64(radius), false), + }); + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, 3), + input: NodeInput::value(TaggedValue::F64(radius / 2.), false), + }); + } + } + responses.add(GraphOperationMessage::TransformSet { layer, - transform: DAffine2::from_scale_angle_translation((end - start).abs(), 0., (start + end) / 2.), + transform: DAffine2::from_scale_angle_translation(scale, 0., (start + end) / 2.), transform_in: TransformIn::Viewport, skip_rerender: false, }); + + responses.add(NodeGraphMessage::RunDocumentGraph); } } diff --git a/editor/src/messages/tool/tool_messages/rectangle_tool.rs b/editor/src/messages/tool/tool_messages/rectangle_tool.rs index 89b2c41c..09b58902 100644 --- a/editor/src/messages/tool/tool_messages/rectangle_tool.rs +++ b/editor/src/messages/tool/tool_messages/rectangle_tool.rs @@ -1,7 +1,7 @@ use super::tool_prelude::*; use crate::consts::DEFAULT_STROKE_WIDTH; use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type; -use crate::messages::portfolio::document::{graph_operation::utility_types::TransformIn, overlays::utility_types::OverlayContext}; +use crate::messages::portfolio::document::{graph_operation::utility_types::TransformIn, overlays::utility_types::OverlayContext, utility_types::network_interface::InputConnector}; use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::graph_modification_utils; @@ -225,12 +225,26 @@ impl Fsm for RectangleToolFsmState { if let Some([start, end]) = shape_data.calculate_points(document, input, center, lock_ratio) { if let Some(layer) = shape_data.layer { // TODO: make the scale impact the rect node + let Some(node_id) = graph_modification_utils::get_rectangle_id(layer, &document.network_interface) else { + return self; + }; + + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, 1), + input: NodeInput::value(TaggedValue::F64((start.x - end.x).abs()), false), + }); + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, 2), + input: NodeInput::value(TaggedValue::F64((start.y - end.y).abs()), false), + }); responses.add(GraphOperationMessage::TransformSet { layer, - transform: DAffine2::from_scale_angle_translation((end - start).abs(), 0., (start + end) / 2.), + transform: DAffine2::from_translation((start + end) / 2.), transform_in: TransformIn::Viewport, skip_rerender: false, }); + + responses.add(NodeGraphMessage::RunDocumentGraph); } }