mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-24 17:58:12 +08:00
Add "Spiral" to the Shape tool and as a new node (#2803)
* made spiral node * number of turns in decimal and arc-angle implementation * logarithmic spiral * unified log and arc spiral into spiral node * add spiral shape in shape tool * fix min value and degree unit * make it compile * updated the api * changed the function_name * [/] to update the turns widget in shape tool * Code review --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
ee586be381
commit
485152bf8d
@@ -363,6 +363,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_spiral_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<NodeId> {
|
||||
NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Spiral")
|
||||
}
|
||||
|
||||
pub fn get_text_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<NodeId> {
|
||||
NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name("Text")
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ pub mod line_shape;
|
||||
pub mod polygon_shape;
|
||||
pub mod rectangle_shape;
|
||||
pub mod shape_utility;
|
||||
pub mod spiral_shape;
|
||||
pub mod star_shape;
|
||||
|
||||
pub use super::shapes::ellipse_shape::Ellipse;
|
||||
|
||||
@@ -158,34 +158,34 @@ impl Polygon {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn increase_decrease_sides(increase: bool, document: &DocumentMessageHandler, shape_tool_data: &mut ShapeToolData, responses: &mut VecDeque<Message>) {
|
||||
if let Some(layer) = shape_tool_data.data.layer {
|
||||
let Some(node_id) = graph_modification_utils::get_polygon_id(layer, &document.network_interface).or(graph_modification_utils::get_star_id(layer, &document.network_interface)) else {
|
||||
return;
|
||||
};
|
||||
/// Updates the number of sides of a polygon or star node and syncs the Shape tool UI widget accordingly.
|
||||
/// Increases or decreases the side count based on user input, clamped to a minimum of 3.
|
||||
pub fn decrease_or_increase_sides(decrease: bool, layer: LayerNodeIdentifier, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
let Some(node_id) = graph_modification_utils::get_polygon_id(layer, &document.network_interface).or(graph_modification_utils::get_star_id(layer, &document.network_interface)) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(node_inputs) = NodeGraphLayer::new(layer, &document.network_interface)
|
||||
.find_node_inputs("Regular Polygon")
|
||||
.or(NodeGraphLayer::new(layer, &document.network_interface).find_node_inputs("Star"))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(node_inputs) = NodeGraphLayer::new(layer, &document.network_interface)
|
||||
.find_node_inputs("Regular Polygon")
|
||||
.or(NodeGraphLayer::new(layer, &document.network_interface).find_node_inputs("Star"))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(&TaggedValue::U32(n)) = node_inputs.get(1).unwrap().as_value() else {
|
||||
return;
|
||||
};
|
||||
let Some(&TaggedValue::U32(n)) = node_inputs.get(1).unwrap().as_value() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let new_dimension = if increase { n + 1 } else { (n - 1).max(3) };
|
||||
let new_dimension = if decrease { (n - 1).max(3) } else { n + 1 };
|
||||
|
||||
responses.add(ShapeToolMessage::UpdateOptions {
|
||||
options: ShapeOptionsUpdate::Vertices(new_dimension),
|
||||
});
|
||||
responses.add(ShapeToolMessage::UpdateOptions {
|
||||
options: ShapeOptionsUpdate::Vertices(new_dimension),
|
||||
});
|
||||
|
||||
responses.add(NodeGraphMessage::SetInput {
|
||||
input_connector: InputConnector::node(node_id, 1),
|
||||
input: NodeInput::value(TaggedValue::U32(new_dimension), false),
|
||||
});
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
responses.add(NodeGraphMessage::SetInput {
|
||||
input_connector: InputConnector::node(node_id, 1),
|
||||
input: NodeInput::value(TaggedValue::U32(new_dimension), false),
|
||||
});
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ pub enum ShapeType {
|
||||
Star,
|
||||
Circle,
|
||||
Arc,
|
||||
Spiral,
|
||||
Grid,
|
||||
Rectangle,
|
||||
Ellipse,
|
||||
@@ -43,6 +44,7 @@ impl ShapeType {
|
||||
Self::Circle => "Circle",
|
||||
Self::Arc => "Arc",
|
||||
Self::Grid => "Grid",
|
||||
Self::Spiral => "Spiral",
|
||||
Self::Rectangle => "Rectangle",
|
||||
Self::Ellipse => "Ellipse",
|
||||
Self::Line => "Line",
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
use super::*;
|
||||
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::utility_types::document_metadata::LayerNodeIdentifier;
|
||||
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeTemplate};
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils::{self, NodeGraphLayer};
|
||||
use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapData, SnapTypeConfiguration};
|
||||
use crate::messages::tool::tool_messages::shape_tool::ShapeOptionsUpdate;
|
||||
use crate::messages::tool::tool_messages::tool_prelude::*;
|
||||
use glam::DAffine2;
|
||||
use graph_craft::document::NodeInput;
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graphene_std::NodeInputDecleration;
|
||||
use graphene_std::vector::misc::SpiralType;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Spiral;
|
||||
|
||||
impl Spiral {
|
||||
pub fn create_node(spiral_type: SpiralType, turns: f64) -> NodeTemplate {
|
||||
let inner_radius = match spiral_type {
|
||||
SpiralType::Archimedean => 0.,
|
||||
SpiralType::Logarithmic => 0.1,
|
||||
};
|
||||
|
||||
let node_type = resolve_document_node_type("Spiral").expect("Spiral node can't be found");
|
||||
node_type.node_template_input_override([
|
||||
None,
|
||||
Some(NodeInput::value(TaggedValue::SpiralType(spiral_type), false)),
|
||||
Some(NodeInput::value(TaggedValue::F64(turns), false)),
|
||||
Some(NodeInput::value(TaggedValue::F64(0.), false)),
|
||||
Some(NodeInput::value(TaggedValue::F64(inner_radius), false)),
|
||||
Some(NodeInput::value(TaggedValue::F64(0.1), false)),
|
||||
Some(NodeInput::value(TaggedValue::F64(90.), false)),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn update_shape(document: &DocumentMessageHandler, ipp: &InputPreprocessorMessageHandler, layer: LayerNodeIdentifier, shape_tool_data: &mut ShapeToolData, responses: &mut VecDeque<Message>) {
|
||||
use graphene_std::vector::generator_nodes::spiral::*;
|
||||
|
||||
let viewport_drag_start = shape_tool_data.data.viewport_drag_start(document);
|
||||
|
||||
let ignore = vec![layer];
|
||||
let snap_data = SnapData::ignore(document, ipp, &ignore);
|
||||
let config = SnapTypeConfiguration::default();
|
||||
let document_mouse = document.metadata().document_to_viewport.inverse().transform_point2(ipp.mouse.position);
|
||||
let snapped = shape_tool_data.data.snap_manager.free_snap(&snap_data, &SnapCandidatePoint::handle(document_mouse), config);
|
||||
let snapped_viewport_point = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
shape_tool_data.data.snap_manager.update_indicator(snapped);
|
||||
|
||||
let dragged_distance = (viewport_drag_start - snapped_viewport_point).length();
|
||||
|
||||
let Some(node_id) = graph_modification_utils::get_spiral_id(layer, &document.network_interface) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(node_inputs) = NodeGraphLayer::new(layer, &document.network_interface).find_node_inputs("Spiral") else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(&TaggedValue::SpiralType(spiral_type)) = node_inputs.get(SpiralTypeInput::INDEX).unwrap().as_value() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let new_radius = match spiral_type {
|
||||
SpiralType::Archimedean => dragged_distance,
|
||||
SpiralType::Logarithmic => (dragged_distance).max(0.1),
|
||||
};
|
||||
|
||||
responses.add(GraphOperationMessage::TransformSet {
|
||||
layer,
|
||||
transform: DAffine2::from_scale_angle_translation(DVec2::ONE, 0., viewport_drag_start),
|
||||
transform_in: TransformIn::Viewport,
|
||||
skip_rerender: false,
|
||||
});
|
||||
|
||||
responses.add(NodeGraphMessage::SetInput {
|
||||
input_connector: InputConnector::node(node_id, OuterRadiusInput::INDEX),
|
||||
input: NodeInput::value(TaggedValue::F64(new_radius), false),
|
||||
});
|
||||
}
|
||||
|
||||
/// Updates the number of turns of a Spiral node and recalculates its radius based on drag distance.
|
||||
/// Also updates the Shape tool's turns UI widget to reflect the change.
|
||||
pub fn update_turns(decrease: bool, layer: LayerNodeIdentifier, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
use graphene_std::vector::generator_nodes::spiral::*;
|
||||
|
||||
let Some(node_inputs) = NodeGraphLayer::new(layer, &document.network_interface).find_node_inputs("Spiral") else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(node_id) = graph_modification_utils::get_spiral_id(layer, &document.network_interface) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(&TaggedValue::F64(mut turns)) = node_inputs.get(TurnsInput::INDEX).unwrap().as_value() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if decrease {
|
||||
turns = (turns - 1.).max(1.);
|
||||
} else {
|
||||
turns += 1.;
|
||||
}
|
||||
|
||||
responses.add(ShapeToolMessage::UpdateOptions {
|
||||
options: ShapeOptionsUpdate::Turns(turns),
|
||||
});
|
||||
|
||||
responses.add(NodeGraphMessage::SetInput {
|
||||
input_connector: InputConnector::node(node_id, TurnsInput::INDEX),
|
||||
input: NodeInput::value(TaggedValue::F64(turns), false),
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user