Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Spline tool behavior to use Path and Spline from Points nodes instead of legacy Spline node #2200

Merged
merged 2 commits into from
Jan 15, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 60 additions & 18 deletions editor/src/messages/tool/tool_messages/spline_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio
use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::snapping::SnapManager;

use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graph_craft::document::{NodeId, NodeInput};
use graphene_core::Color;
use graphene_std::vector::{PointId, SegmentId, VectorModificationType};

#[derive(Default)]
pub struct SplineTool {
Expand Down Expand Up @@ -177,8 +178,14 @@ impl ToolTransition for SplineTool {

#[derive(Clone, Debug, Default)]
struct SplineToolData {
points: Vec<DVec2>,
/// Points that are inserted.
points: Vec<(PointId, DVec2)>,
/// Point to be inserted.
next_point: DVec2,
/// Point that was inserted temporarily to show preview.
preview_point: Option<PointId>,
/// Segment that was inserted temporarily to show preview.
preview_segment: Option<SegmentId>,
weight: f64,
layer: Option<LayerNodeIdentifier>,
snap_manager: SnapManager,
Expand All @@ -205,9 +212,11 @@ impl Fsm for SplineToolFsmState {

tool_data.weight = tool_options.line_weight;

let node_type = resolve_document_node_type("Spline").expect("Spline node does not exist");
let node = node_type.node_template_input_override([None, Some(NodeInput::value(TaggedValue::VecDVec2(Vec::new()), false))]);
let nodes = vec![(NodeId(0), node)];
let path_node_type = resolve_document_node_type("Path").expect("Path node does not exist");
let path_node = path_node_type.default_node_template();
let spline_node_type = resolve_document_node_type("Splines from Points").expect("Spline from Points node does not exist");
let spline_node = spline_node_type.node_template_input_override([Some(NodeInput::node(NodeId(1), 0))]);
let nodes = vec![(NodeId(1), path_node), (NodeId(0), spline_node)];

let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, parent, responses);
tool_options.fill.apply_fill(layer, responses);
Expand All @@ -228,12 +237,11 @@ impl Fsm for SplineToolFsmState {
let transform = document.metadata().transform_to_viewport(layer);
let pos = transform.inverse().transform_point2(snapped_position);

if tool_data.points.last().map_or(true, |last_pos| last_pos.distance(pos) > DRAG_THRESHOLD) {
tool_data.points.push(pos);
if tool_data.points.last().map_or(true, |last_pos| last_pos.1.distance(pos) > DRAG_THRESHOLD) {
tool_data.next_point = pos;
}

update_spline(document, tool_data, true, responses);
update_spline(tool_data, false, responses);

SplineToolFsmState::Drawing
}
Expand All @@ -246,7 +254,7 @@ impl Fsm for SplineToolFsmState {
let pos = transform.inverse().transform_point2(snapped_position);
tool_data.next_point = pos;

update_spline(document, tool_data, true, responses);
update_spline(tool_data, true, responses);

// Auto-panning
let messages = [SplineToolMessage::PointerOutsideViewport.into(), SplineToolMessage::PointerMove.into()];
Expand All @@ -269,13 +277,15 @@ impl Fsm for SplineToolFsmState {
}
(SplineToolFsmState::Drawing, SplineToolMessage::Confirm | SplineToolMessage::Abort) => {
if tool_data.points.len() >= 2 {
update_spline(document, tool_data, false, responses);
delete_preview(tool_data, responses);
responses.add(DocumentMessage::EndTransaction);
} else {
responses.add(DocumentMessage::AbortTransaction);
}

tool_data.layer = None;
tool_data.preview_point = None;
tool_data.preview_segment = None;
tool_data.points.clear();
tool_data.snap_manager.cleanup(responses);

Expand Down Expand Up @@ -310,17 +320,49 @@ impl Fsm for SplineToolFsmState {
}
}

fn update_spline(document: &DocumentMessageHandler, tool_data: &SplineToolData, show_preview: bool, responses: &mut VecDeque<Message>) {
let mut points = tool_data.points.clone();
fn update_spline(tool_data: &mut SplineToolData, show_preview: bool, responses: &mut VecDeque<Message>) {
delete_preview(tool_data, responses);

let Some(layer) = tool_data.layer else { return };

let next_point_pos = tool_data.next_point;
let next_point_id = PointId::generate();
let modification_type = VectorModificationType::InsertPoint {
id: next_point_id,
position: next_point_pos,
};
responses.add(GraphOperationMessage::Vector { layer, modification_type });

if let Some((last_point_id, _)) = tool_data.points.last() {
let points = [*last_point_id, next_point_id];
let id = SegmentId::generate();
let modification_type = VectorModificationType::InsertSegment { id, points, handles: [None, None] };
responses.add(GraphOperationMessage::Vector { layer, modification_type });

if show_preview {
tool_data.preview_segment = Some(id);
}
}

if show_preview {
points.push(tool_data.next_point)
tool_data.preview_point = Some(next_point_id);
} else {
tool_data.points.push((next_point_id, next_point_pos));
}
let value = TaggedValue::VecDVec2(points);
}

fn delete_preview(tool_data: &mut SplineToolData, responses: &mut VecDeque<Message>) {
let Some(layer) = tool_data.layer else { return };

let Some(node_id) = graph_modification_utils::NodeGraphLayer::new(layer, &document.network_interface).upstream_node_id_from_name("Spline") else {
return;
};
responses.add_front(NodeGraphMessage::SetInputValue { node_id, input_index: 1, value });
if let Some(id) = tool_data.preview_point {
let modification_type = VectorModificationType::RemovePoint { id };
responses.add(GraphOperationMessage::Vector { layer, modification_type });
}
if let Some(id) = tool_data.preview_segment {
let modification_type = VectorModificationType::RemoveSegment { id };
responses.add(GraphOperationMessage::Vector { layer, modification_type });
}

tool_data.preview_point = None;
tool_data.preview_segment = None;
}
Loading