Add an arrow to the Shape tool (#3343)

* add arrow shape feature in editor

Signed-off-by: krVatsal <kumarvatsal34@gmail.com>

* fix the arrow tool to show arrow in viewport space

Signed-off-by: krVatsal <kumarvatsal34@gmail.com>

* fix the direction of arrow and make the new arrow node

Signed-off-by: krVatsal <kumarvatsal34@gmail.com>

* updated arrow tool to hae start and end points

Signed-off-by: krVatsal <kumarvatsal34@gmail.com>

* fixed calculate point bug

Signed-off-by: krVatsal <kumarvatsal34@gmail.com>

* fixed some bugs of arrow positioning

Signed-off-by: krVatsal <kumarvatsal34@gmail.com>

* fixed formatting in whole codebase and added fill to arrow

Signed-off-by: krVatsal <kumarvatsal34@gmail.com>

* fix

---------

Signed-off-by: krVatsal <kumarvatsal34@gmail.com>
Co-authored-by: Timon <me@timon.zip>
This commit is contained in:
Vatsal Kumar
2026-01-12 00:58:28 +00:00
committed by GitHub
co-authored by Timon
parent 479688d86b
commit 4fea2b0fe7
7 changed files with 186 additions and 8 deletions
@@ -364,6 +364,10 @@ pub fn get_arc_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInt
NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Arc")
}
pub fn get_arrow_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<NodeId> {
NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Arrow")
}
pub fn get_spiral_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<NodeId> {
NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Spiral")
}
@@ -0,0 +1,90 @@
use super::shape_utility::ShapeToolModifierKey;
use super::*;
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::network_interface::{InputConnector, NodeTemplate};
use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::graph_modification_utils;
use glam::DVec2;
use graph_craft::document::NodeInput;
use graph_craft::document::value::TaggedValue;
use std::collections::VecDeque;
#[derive(Default)]
pub struct Arrow;
impl Arrow {
pub fn create_node(document: &DocumentMessageHandler, drag_start: DVec2) -> NodeTemplate {
let node_type = resolve_document_node_type("Arrow").expect("Arrow node does not exist");
let viewport_pos = document.metadata().document_to_viewport.transform_point2(drag_start);
node_type.node_template_input_override([
None,
Some(NodeInput::value(TaggedValue::DVec2(viewport_pos), false)), // start
Some(NodeInput::value(TaggedValue::DVec2(viewport_pos), false)), // end
Some(NodeInput::value(TaggedValue::F64(10.), false)), // shaft_width
Some(NodeInput::value(TaggedValue::F64(30.), false)), // head_width
Some(NodeInput::value(TaggedValue::F64(20.), false)), // head_length
])
}
pub fn update_shape(
document: &DocumentMessageHandler,
input: &InputPreprocessorMessageHandler,
_viewport: &ViewportMessageHandler,
layer: LayerNodeIdentifier,
tool_data: &mut ShapeToolData,
_modifier: ShapeToolModifierKey,
responses: &mut VecDeque<Message>,
) {
// Track current mouse position in viewport space
tool_data.line_data.drag_current = input.mouse.position;
// Convert both points to document space (matching Line tool pattern)
let document_to_viewport = document.metadata().document_to_viewport;
let start_document = tool_data.data.drag_start;
let end_document = document_to_viewport.inverse().transform_point2(tool_data.line_data.drag_current);
// Calculate length in document space for validation
let delta = end_document - start_document;
let length_document = delta.length();
if length_document < 1e-6 {
return;
}
let Some(node_id) = graph_modification_utils::get_arrow_id(layer, &document.network_interface) else {
return;
};
// Calculate proportional dimensions based on arrow length
let shaft_width = length_document * 0.1;
let head_width = length_document * 0.3;
let head_length = length_document * 0.2;
// Update Arrow node parameters with document space coordinates (like Line tool)
responses.add(NodeGraphMessage::SetInput {
input_connector: InputConnector::node(node_id, 1),
input: NodeInput::value(TaggedValue::DVec2(start_document), false),
});
responses.add(NodeGraphMessage::SetInput {
input_connector: InputConnector::node(node_id, 2),
input: NodeInput::value(TaggedValue::DVec2(end_document), false),
});
responses.add(NodeGraphMessage::SetInput {
input_connector: InputConnector::node(node_id, 3),
input: NodeInput::value(TaggedValue::F64(shaft_width), false),
});
responses.add(NodeGraphMessage::SetInput {
input_connector: InputConnector::node(node_id, 4),
input: NodeInput::value(TaggedValue::F64(head_width), false),
});
responses.add(NodeGraphMessage::SetInput {
input_connector: InputConnector::node(node_id, 5),
input: NodeInput::value(TaggedValue::F64(head_length), false),
});
responses.add(NodeGraphMessage::RunDocumentGraph);
}
pub fn overlays(_document: &DocumentMessageHandler, _tool_data: &ShapeToolData, _overlay_context: &mut OverlayContext) {}
}
@@ -1,4 +1,5 @@
pub mod arc_shape;
pub mod arrow_shape;
pub mod circle_shape;
pub mod ellipse_shape;
pub mod grid_shape;
@@ -9,6 +10,7 @@ pub mod shape_utility;
pub mod spiral_shape;
pub mod star_shape;
pub use super::shapes::arrow_shape::Arrow;
pub use super::shapes::ellipse_shape::Ellipse;
pub use super::shapes::line_shape::{Line, LineEnd};
pub use super::shapes::rectangle_shape::Rectangle;
@@ -33,6 +33,7 @@ pub enum ShapeType {
Grid,
Rectangle,
Ellipse,
Arrow,
Line,
}
@@ -47,6 +48,7 @@ impl ShapeType {
Self::Spiral => "Spiral",
Self::Rectangle => "Rectangle",
Self::Ellipse => "Ellipse",
Self::Arrow => "Arrow",
Self::Line => "Line",
})
.into()
@@ -57,6 +59,7 @@ impl ShapeType {
Self::Line => "Line Tool",
Self::Rectangle => "Rectangle Tool",
Self::Ellipse => "Ellipse Tool",
Self::Arrow => "Arrow Tool",
_ => "",
})
.into()
@@ -75,6 +78,7 @@ impl ShapeType {
Self::Line => "VectorLineTool",
Self::Rectangle => "VectorRectangleTool",
Self::Ellipse => "VectorEllipseTool",
Self::Arrow => "VectorArrowTool",
_ => "",
})
.into()
@@ -85,6 +89,7 @@ impl ShapeType {
Self::Line => ToolType::Line,
Self::Rectangle => ToolType::Rectangle,
Self::Ellipse => ToolType::Ellipse,
Self::Arrow => ToolType::Shape,
_ => ToolType::Shape,
}
}