Skip to content

Commit c42011f

Browse files
4adexKeavon
andauthored
Partly fix when the "Make Path Editable" button is shown as enabled (#2968)
* Fix add path node button enable * Fix add path node button enable * Refactor code * Fix formatting * Clean up logic --------- Co-authored-by: Keavon Chambers <[email protected]>
1 parent b9a1b2e commit c42011f

File tree

5 files changed

+53
-90
lines changed

5 files changed

+53
-90
lines changed

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ use crate::messages::portfolio::document::utility_types::wires::{GraphWireStyle,
1717
use crate::messages::prelude::*;
1818
use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
1919
use crate::messages::tool::common_functionality::graph_modification_utils::{self, get_clip_mode};
20+
use crate::messages::tool::common_functionality::utility_functions::make_path_editable_is_allowed;
2021
use crate::messages::tool::tool_messages::tool_prelude::{Key, MouseMotion};
2122
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
2223
use bezier_rs::Subpath;
2324
use glam::{DAffine2, DVec2, IVec2};
24-
use graph_craft::document::value::TaggedValue;
2525
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput};
2626
use graph_craft::proto::GraphErrors;
2727
use graphene_std::math::math_ext::QuadExt;
@@ -126,35 +126,9 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
126126
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![new_layer_id] });
127127
}
128128
NodeGraphMessage::AddPathNode => {
129-
let selected_nodes = network_interface.selected_nodes();
130-
let mut selected_layers = selected_nodes.selected_layers(network_interface.document_metadata());
131-
let first_layer = selected_layers.next();
132-
let second_layer = selected_layers.next();
133-
let has_single_selection = first_layer.is_some() && second_layer.is_none();
134-
135-
let compatible_type = first_layer.and_then(|layer| {
136-
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, &network_interface);
137-
graph_layer.horizontal_layer_flow().nth(1).and_then(|node_id| {
138-
let (output_type, _) = network_interface.output_type(&node_id, 0, &[]);
139-
Some(format!("type:{}", output_type.nested_type()))
140-
})
141-
});
142-
143-
let is_compatible = compatible_type.as_deref() == Some("type:Instances<VectorData>");
144-
145-
if first_layer.is_some() && has_single_selection && is_compatible {
146-
if let Some(layer) = first_layer {
147-
let node_type = "Path".to_string();
148-
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, &network_interface);
149-
let is_modifiable = matches!(graph_layer.find_input("Path", 1), Some(TaggedValue::VectorModification(_)));
150-
if !is_modifiable {
151-
responses.add(NodeGraphMessage::CreateNodeInLayerWithTransaction {
152-
node_type: node_type.clone(),
153-
layer: LayerNodeIdentifier::new_unchecked(layer.to_node()),
154-
});
155-
responses.add(BroadcastEvent::SelectionChanged);
156-
}
157-
}
129+
if let Some(layer) = make_path_editable_is_allowed(network_interface, network_interface.document_metadata()) {
130+
responses.add(NodeGraphMessage::CreateNodeInLayerWithTransaction { node_type: "Path".to_string(), layer });
131+
responses.add(BroadcastEvent::SelectionChanged);
158132
}
159133
}
160134
NodeGraphMessage::AddImport => {

editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct MenuBarMessageHandler {
1919
pub spreadsheet_view_open: bool,
2020
pub message_logging_verbosity: MessageLoggingVerbosity,
2121
pub reset_node_definitions_on_open: bool,
22-
pub single_path_node_compatible_layer_selected: bool,
22+
pub make_path_editable_is_allowed: bool,
2323
}
2424

2525
#[message_handler_data]
@@ -46,7 +46,7 @@ impl LayoutHolder for MenuBarMessageHandler {
4646
let message_logging_verbosity_names = self.message_logging_verbosity == MessageLoggingVerbosity::Names;
4747
let message_logging_verbosity_contents = self.message_logging_verbosity == MessageLoggingVerbosity::Contents;
4848
let reset_node_definitions_on_open = self.reset_node_definitions_on_open;
49-
let single_path_node_compatible_layer_selected = self.single_path_node_compatible_layer_selected;
49+
let make_path_editable_is_allowed = self.make_path_editable_is_allowed;
5050

5151
let menu_bar_entries = vec![
5252
MenuBarEntry {
@@ -442,7 +442,7 @@ impl LayoutHolder for MenuBarMessageHandler {
442442
icon: Some("NodeShape".into()),
443443
shortcut: None,
444444
action: MenuBarEntry::create_action(|_| NodeGraphMessage::AddPathNode.into()),
445-
disabled: !single_path_node_compatible_layer_selected,
445+
disabled: !make_path_editable_is_allowed,
446446
..MenuBarEntry::default()
447447
}],
448448
]),

editor/src/messages/portfolio/portfolio_message_handler.rs

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ use crate::messages::portfolio::document_migration::*;
2020
use crate::messages::preferences::SelectionMode;
2121
use crate::messages::prelude::*;
2222
use crate::messages::tool::common_functionality::graph_modification_utils;
23+
use crate::messages::tool::common_functionality::utility_functions::make_path_editable_is_allowed;
2324
use crate::messages::tool::utility_types::{HintData, HintGroup, ToolType};
2425
use crate::node_graph_executor::{ExportConfig, NodeGraphExecutor};
2526
use bezier_rs::BezierHandles;
2627
use glam::{DAffine2, DVec2};
2728
use graph_craft::document::NodeId;
28-
use graph_craft::document::value::TaggedValue;
2929
use graphene_std::Color;
3030
use graphene_std::renderer::Quad;
3131
use graphene_std::text::Font;
@@ -84,7 +84,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
8484
self.menu_bar_message_handler.has_selected_nodes = false;
8585
self.menu_bar_message_handler.has_selected_layers = false;
8686
self.menu_bar_message_handler.has_selection_history = (false, false);
87-
self.menu_bar_message_handler.single_path_node_compatible_layer_selected = false;
87+
self.menu_bar_message_handler.make_path_editable_is_allowed = false;
8888
self.menu_bar_message_handler.spreadsheet_view_open = self.spreadsheet.spreadsheet_view_open;
8989
self.menu_bar_message_handler.message_logging_verbosity = message_logging_verbosity;
9090
self.menu_bar_message_handler.reset_node_definitions_on_open = reset_node_definitions_on_open;
@@ -102,30 +102,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
102102
let metadata = &document.network_interface.document_network_metadata().persistent_metadata;
103103
(!metadata.selection_undo_history.is_empty(), !metadata.selection_redo_history.is_empty())
104104
};
105-
self.menu_bar_message_handler.single_path_node_compatible_layer_selected = {
106-
let selected_nodes = document.network_interface.selected_nodes();
107-
let mut selected_layers = selected_nodes.selected_layers(document.metadata());
108-
let first_layer = selected_layers.next();
109-
let second_layer = selected_layers.next();
110-
let has_single_selection = first_layer.is_some() && second_layer.is_none();
111-
112-
let compatible_type = first_layer.and_then(|layer| {
113-
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, &document.network_interface);
114-
graph_layer.horizontal_layer_flow().nth(1).map(|node_id| {
115-
let (output_type, _) = document.network_interface.output_type(&node_id, 0, &[]);
116-
format!("type:{}", output_type.nested_type())
117-
})
118-
});
119-
120-
let is_compatible = compatible_type.as_deref() == Some("type:Instances<VectorData>");
121-
122-
let is_modifiable = first_layer.is_some_and(|layer| {
123-
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, &document.network_interface);
124-
matches!(graph_layer.find_input("Path", 1), Some(TaggedValue::VectorModification(_)))
125-
});
126-
127-
first_layer.is_some() && has_single_selection && is_compatible && !is_modifiable
128-
}
105+
self.menu_bar_message_handler.make_path_editable_is_allowed = make_path_editable_is_allowed(&document.network_interface, document.metadata()).is_some();
129106
}
130107

131108
self.menu_bar_message_handler.process_message(message, responses, ());

editor/src/messages/tool/common_functionality/utility_functions.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
use super::snapping::{SnapCandidatePoint, SnapData, SnapManager};
22
use super::transformation_cage::{BoundingBoxManager, SizeSnapData};
33
use crate::consts::ROTATE_INCREMENT;
4-
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
4+
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
5+
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
56
use crate::messages::portfolio::document::utility_types::transformation::Selected;
67
use crate::messages::prelude::*;
7-
use crate::messages::tool::common_functionality::graph_modification_utils::get_text;
8+
use crate::messages::tool::common_functionality::graph_modification_utils::{NodeGraphLayer, get_text};
89
use crate::messages::tool::common_functionality::transformation_cage::SelectedEdges;
910
use crate::messages::tool::tool_messages::path_tool::PathOverlayMode;
1011
use crate::messages::tool::utility_types::ToolType;
1112
use bezier_rs::{Bezier, BezierHandles};
1213
use glam::{DAffine2, DVec2};
14+
use graph_craft::concrete;
15+
use graph_craft::document::value::TaggedValue;
1316
use graphene_std::renderer::Quad;
1417
use graphene_std::text::{FontCache, load_font};
15-
use graphene_std::vector::{HandleExt, HandleId, ManipulatorPointId, PointId, SegmentId, VectorData, VectorModificationType};
18+
use graphene_std::vector::{HandleExt, HandleId, ManipulatorPointId, PointId, SegmentId, VectorData, VectorDataTable, VectorModification, VectorModificationType};
1619
use kurbo::{CubicBez, Line, ParamCurveExtrema, PathSeg, Point, QuadBez};
1720

1821
/// Determines if a path should be extended. Goal in viewport space. Returns the path and if it is extending from the start, if applicable.
@@ -586,3 +589,36 @@ pub fn find_two_param_best_approximate(p1: DVec2, p3: DVec2, d1: DVec2, d2: DVec
586589

587590
(d1 * len1, d2 * len2)
588591
}
592+
593+
pub fn make_path_editable_is_allowed(network_interface: &NodeNetworkInterface, metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
594+
// Must have exactly one layer selected
595+
let selected_nodes = network_interface.selected_nodes();
596+
let mut selected_layers = selected_nodes.selected_layers(metadata);
597+
let first_layer = selected_layers.next()?;
598+
if selected_layers.next().is_some() {
599+
return None;
600+
}
601+
602+
// Must be a layer of type VectorDataTable
603+
let compatible_type = NodeGraphLayer::new(first_layer, network_interface)
604+
.horizontal_layer_flow()
605+
.nth(1)
606+
.map(|node_id| {
607+
let (output_type, _) = network_interface.output_type(&node_id, 0, &[]);
608+
output_type.nested_type() == concrete!(VectorDataTable).nested_type()
609+
})
610+
.unwrap_or_default();
611+
if !compatible_type {
612+
return None;
613+
}
614+
615+
// Must not already have an existing Path node, in the right-most part of the layer chain, which has an empty set of modifications
616+
// (otherwise users could repeatedly keep running this command and stacking up empty Path nodes)
617+
if let Some(TaggedValue::VectorModification(modifications)) = NodeGraphLayer::new(first_layer, network_interface).find_input("Path", 1) {
618+
if modifications.as_ref() == &VectorModification::default() {
619+
return None;
620+
}
621+
}
622+
623+
Some(first_layer)
624+
}

editor/src/messages/tool/tool_messages/path_tool.rs

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ use crate::messages::tool::common_functionality::shape_editor::{
2020
ClosestSegment, ManipulatorAngle, OpposingHandleLengths, SelectedLayerState, SelectedPointsInfo, SelectionChange, SelectionShape, SelectionShapeType, ShapeState,
2121
};
2222
use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager};
23-
use crate::messages::tool::common_functionality::utility_functions::{calculate_segment_angle, find_two_param_best_approximate};
23+
use crate::messages::tool::common_functionality::utility_functions::{calculate_segment_angle, find_two_param_best_approximate, make_path_editable_is_allowed};
2424
use bezier_rs::{Bezier, BezierHandles, TValue};
25-
use graph_craft::document::value::TaggedValue;
2625
use graphene_std::Color;
2726
use graphene_std::renderer::Quad;
2827
use graphene_std::transform::ReferencePoint;
@@ -291,7 +290,7 @@ impl LayoutHolder for PathTool {
291290
.icon(Some("NodeShape".into()))
292291
.tooltip("Make Path Editable")
293292
.on_update(|_| NodeGraphMessage::AddPathNode.into())
294-
.disabled(!self.tool_data.single_path_node_compatible_layer_selected)
293+
.disabled(!self.tool_data.make_path_editable_is_allowed)
295294
.widget_holder();
296295

297296
let [_checkbox, _dropdown] = {
@@ -571,7 +570,7 @@ struct PathToolData {
571570
drill_through_cycle_count: usize,
572571
hovered_layers: Vec<LayerNodeIdentifier>,
573572
ghost_outline: Vec<(Vec<ClickTargetType>, LayerNodeIdentifier)>,
574-
single_path_node_compatible_layer_selected: bool,
573+
make_path_editable_is_allowed: bool,
575574
}
576575

577576
impl PathToolData {
@@ -3014,30 +3013,7 @@ impl Fsm for PathToolFsmState {
30143013
colinear,
30153014
};
30163015

3017-
tool_data.single_path_node_compatible_layer_selected = {
3018-
let selected_nodes = document.network_interface.selected_nodes();
3019-
let mut selected_layers = selected_nodes.selected_layers(document.metadata());
3020-
let first_layer = selected_layers.next();
3021-
let second_layer = selected_layers.next();
3022-
let has_single_selection = first_layer.is_some() && second_layer.is_none();
3023-
3024-
let compatible_type = first_layer.and_then(|layer| {
3025-
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, &document.network_interface);
3026-
graph_layer.horizontal_layer_flow().nth(1).map(|node_id| {
3027-
let (output_type, _) = document.network_interface.output_type(&node_id, 0, &[]);
3028-
format!("type:{}", output_type.nested_type())
3029-
})
3030-
});
3031-
3032-
let is_compatible = compatible_type.as_deref() == Some("type:Instances<VectorData>");
3033-
3034-
let is_modifiable = first_layer.is_some_and(|layer| {
3035-
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, &document.network_interface);
3036-
matches!(graph_layer.find_input("Path", 1), Some(TaggedValue::VectorModification(_)))
3037-
});
3038-
3039-
first_layer.is_some() && has_single_selection && is_compatible && !is_modifiable
3040-
};
3016+
tool_data.make_path_editable_is_allowed = make_path_editable_is_allowed(&document.network_interface, document.metadata()).is_some();
30413017
tool_data.update_selection_status(shape_editor, document);
30423018
self
30433019
}

0 commit comments

Comments
 (0)