@@ -15,6 +15,8 @@ use crate::messages::portfolio::document::utility_types::network_interface::{
15
15
use crate :: messages:: portfolio:: document:: utility_types:: nodes:: { CollapsedLayers , LayerPanelEntry } ;
16
16
use crate :: messages:: prelude:: * ;
17
17
use crate :: messages:: tool:: common_functionality:: auto_panning:: AutoPanning ;
18
+ use crate :: messages:: tool:: tool_messages:: tool_prelude:: { Key , MouseMotion } ;
19
+ use crate :: messages:: tool:: utility_types:: { HintData , HintGroup , HintInfo } ;
18
20
use glam:: { DAffine2 , DVec2 , IVec2 } ;
19
21
use graph_craft:: document:: { DocumentNodeImplementation , NodeId , NodeInput } ;
20
22
use graph_craft:: proto:: GraphErrors ;
@@ -43,14 +45,16 @@ pub struct NodeGraphMessageHandler {
43
45
pub node_graph_errors : GraphErrors ,
44
46
has_selection : bool ,
45
47
widgets : [ LayoutGroup ; 2 ] ,
46
- /// The start position when dragging nodes
47
- pub drag_start : Option < DragStart > ,
48
48
/// Used to add a transaction for the first node move when dragging.
49
49
begin_dragging : bool ,
50
50
/// Used to prevent entering a nested network if the node is dragged after double clicking
51
- drag_occurred : bool ,
52
- /// Stored in node graph coordinates
53
- box_selection_start : Option < DVec2 > ,
51
+ node_has_moved_in_drag : bool ,
52
+ /// If dragging the selected nodes, this stores the starting position both in viewport and node graph coordinates,
53
+ /// plus a flag indicating if it has been dragged since the mousedown began.
54
+ pub drag_start : Option < ( DragStart , bool ) > ,
55
+ /// If dragging the background to create a box selection, this stores its starting point in node graph coordinates,
56
+ /// plus a flag indicating if it has been dragged since the mousedown began.
57
+ box_selection_start : Option < ( DVec2 , bool ) > ,
54
58
/// Restore the selection before box selection if it is aborted
55
59
selection_before_pointer_down : Vec < NodeId > ,
56
60
/// If the grip icon is held during a drag, then shift without pushing other nodes
@@ -294,7 +298,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
294
298
}
295
299
NodeGraphMessage :: EnterNestedNetwork => {
296
300
// Do not enter the nested network if the node was dragged
297
- if self . drag_occurred {
301
+ if self . node_has_moved_in_drag {
298
302
return ;
299
303
}
300
304
@@ -377,7 +381,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
377
381
) else {
378
382
return ;
379
383
} ;
380
- //Ensure that nodes can be grouped by checking if there is an unselected node between selected nodes
384
+ // Ensure that nodes can be grouped by checking if there is an unselected node between selected nodes
381
385
for selected_node_id in & selected_node_ids {
382
386
for input_index in 0 ..network_interface. number_of_inputs ( selected_node_id, breadcrumb_network_path) {
383
387
let input_connector = InputConnector :: node ( * selected_node_id, input_index) ;
@@ -580,8 +584,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
580
584
if right_click {
581
585
// Abort dragging a node
582
586
if self . drag_start . is_some ( ) {
583
- responses. add ( DocumentMessage :: AbortTransaction ) ;
584
587
self . drag_start = None ;
588
+ responses. add ( DocumentMessage :: AbortTransaction ) ;
585
589
responses. add ( NodeGraphMessage :: SelectedNodesSet {
586
590
nodes : self . selection_before_pointer_down . clone ( ) ,
587
591
} ) ;
@@ -598,18 +602,16 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
598
602
}
599
603
// Abort dragging a wire
600
604
if self . wire_in_progress_from_connector . is_some ( ) {
601
- responses. add ( DocumentMessage :: AbortTransaction ) ;
602
605
self . wire_in_progress_from_connector = None ;
603
606
self . wire_in_progress_to_connector = None ;
607
+ responses. add ( DocumentMessage :: AbortTransaction ) ;
604
608
responses. add ( FrontendMessage :: UpdateWirePathInProgress { wire_path : None } ) ;
605
609
return ;
606
610
}
607
611
608
612
let context_menu_data = if let Some ( node_id) = clicked_id {
609
- ContextMenuData :: ToggleLayer {
610
- node_id,
611
- currently_is_node : !network_interface. is_layer ( & node_id, selection_network_path) ,
612
- }
613
+ let currently_is_node = !network_interface. is_layer ( & node_id, selection_network_path) ;
614
+ ContextMenuData :: ToggleLayer { node_id, currently_is_node }
613
615
} else {
614
616
ContextMenuData :: CreateNode
615
617
} ;
@@ -721,6 +723,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
721
723
self . initial_disconnecting = false ;
722
724
723
725
self . wire_in_progress_from_connector = network_interface. output_position ( & clicked_output, selection_network_path) ;
726
+ self . update_node_graph_hints ( responses) ;
724
727
return ;
725
728
}
726
729
@@ -764,9 +767,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
764
767
round_y : 0 ,
765
768
} ;
766
769
767
- self . drag_start = Some ( drag_start) ;
770
+ self . drag_start = Some ( ( drag_start, false ) ) ;
768
771
self . begin_dragging = true ;
769
- self . drag_occurred = false ;
772
+ self . node_has_moved_in_drag = false ;
773
+ self . update_node_graph_hints ( responses) ;
770
774
}
771
775
772
776
// Update the selection if it was modified
@@ -783,7 +787,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
783
787
if !shift_click {
784
788
responses. add ( NodeGraphMessage :: SelectedNodesSet { nodes : Vec :: new ( ) } )
785
789
}
786
- self . box_selection_start = Some ( node_graph_point) ;
790
+ self . box_selection_start = Some ( ( node_graph_point, false ) ) ;
791
+ self . update_node_graph_hints ( responses) ;
787
792
}
788
793
NodeGraphMessage :: PointerMove { shift } => {
789
794
if selection_network_path != breadcrumb_network_path {
@@ -872,11 +877,15 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
872
877
} ;
873
878
responses. add ( FrontendMessage :: UpdateWirePathInProgress { wire_path : Some ( wire_path) } ) ;
874
879
}
875
- } else if let Some ( drag_start) = & mut self . drag_start {
876
- self . drag_occurred = true ;
880
+ } else if let Some ( ( drag_start, dragged) ) = & mut self . drag_start {
881
+ if drag_start. start_x != point. x || drag_start. start_y != point. y {
882
+ * dragged = true ;
883
+ }
884
+
885
+ self . node_has_moved_in_drag = true ;
877
886
if self . begin_dragging {
878
887
self . begin_dragging = false ;
879
- if ipp. keyboard . get ( crate :: messages :: tool :: tool_messages :: tool_prelude :: Key :: Alt as usize ) {
888
+ if ipp. keyboard . get ( Key :: Alt as usize ) {
880
889
responses. add ( NodeGraphMessage :: DuplicateSelectedNodes ) ;
881
890
// Duplicating sets a 2x2 offset, so shift the nodes back to the original position
882
891
responses. add ( NodeGraphMessage :: ShiftSelectedNodesByAmount {
@@ -898,8 +907,12 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
898
907
graph_delta. y -= previous_round_y;
899
908
900
909
responses. add ( NodeGraphMessage :: ShiftSelectedNodesByAmount { graph_delta, rubber_band : true } ) ;
901
- } else if self . box_selection_start . is_some ( ) {
910
+
911
+ self . update_node_graph_hints ( responses) ;
912
+ } else if let Some ( ( _, box_selection_dragged) ) = & mut self . box_selection_start {
913
+ * box_selection_dragged = true ;
902
914
responses. add ( NodeGraphMessage :: UpdateBoxSelection ) ;
915
+ self . update_node_graph_hints ( responses) ;
903
916
} else if self . reordering_import . is_some ( ) {
904
917
let Some ( modify_import_export) = network_interface. modify_import_export ( selection_network_path) else {
905
918
log:: error!( "Could not get modify import export in PointerUp" ) ;
@@ -1016,18 +1029,20 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
1016
1029
}
1017
1030
}
1018
1031
// End of dragging a node
1019
- else if let Some ( drag_start) = & self . drag_start {
1032
+ else if let Some ( ( drag_start, _ ) ) = & self . drag_start {
1020
1033
self . shift_without_push = false ;
1034
+
1021
1035
// Reset all offsets to end the rubber banding while dragging
1022
1036
network_interface. unload_stack_dependents_y_offset ( selection_network_path) ;
1023
1037
let Some ( selected_nodes) = network_interface. selected_nodes_in_nested_network ( selection_network_path) else {
1024
1038
log:: error!( "Could not get selected nodes in PointerUp" ) ;
1025
1039
return ;
1026
1040
} ;
1041
+
1027
1042
// Only select clicked node if multiple are selected and they were not dragged
1028
1043
if let Some ( select_if_not_dragged) = self . select_if_not_dragged {
1029
- if drag_start. start_x == point. x
1030
- && drag_start . start_y == point . y
1044
+ let not_dragged = drag_start. start_x == point. x && drag_start . start_y == point . y ;
1045
+ if not_dragged
1031
1046
&& ( selected_nodes. selected_nodes_ref ( ) . len ( ) != 1
1032
1047
|| selected_nodes
1033
1048
. selected_nodes_ref ( )
@@ -1218,6 +1233,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
1218
1233
responses. add ( FrontendMessage :: UpdateBox { box_selection : None } ) ;
1219
1234
responses. add ( FrontendMessage :: UpdateImportReorderIndex { index : None } ) ;
1220
1235
responses. add ( FrontendMessage :: UpdateExportReorderIndex { index : None } ) ;
1236
+ self . update_node_graph_hints ( responses) ;
1221
1237
}
1222
1238
NodeGraphMessage :: PointerOutsideViewport { shift } => {
1223
1239
if self . drag_start . is_some ( ) || self . box_selection_start . is_some ( ) {
@@ -1306,6 +1322,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
1306
1322
has_left_input_wire,
1307
1323
} ) ;
1308
1324
responses. add ( NodeGraphMessage :: SendSelectedNodes ) ;
1325
+ self . update_node_graph_hints ( responses) ;
1309
1326
}
1310
1327
}
1311
1328
NodeGraphMessage :: SetGridAlignedEdges => {
@@ -1542,7 +1559,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
1542
1559
responses. add ( PropertiesPanelMessage :: Refresh ) ;
1543
1560
}
1544
1561
NodeGraphMessage :: UpdateBoxSelection => {
1545
- if let Some ( box_selection_start) = self . box_selection_start {
1562
+ if let Some ( ( box_selection_start, _ ) ) = self . box_selection_start {
1546
1563
// The mouse button was released but we missed the pointer up event
1547
1564
// if ((e.buttons & 1) === 0) {
1548
1565
// completeBoxSelection();
@@ -1572,7 +1589,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
1572
1589
. inverse ( )
1573
1590
. transform_point2 ( ipp. mouse . position ) ;
1574
1591
1575
- let shift = ipp. keyboard . get ( crate :: messages :: tool :: tool_messages :: tool_prelude :: Key :: Shift as usize ) ;
1592
+ let shift = ipp. keyboard . get ( Key :: Shift as usize ) ;
1576
1593
let Some ( selected_nodes) = network_interface. selected_nodes_in_nested_network ( selection_network_path) else {
1577
1594
log:: error!( "Could not get selected nodes in PointerMove" ) ;
1578
1595
return ;
@@ -1666,6 +1683,9 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
1666
1683
NodeGraphMessage :: UpdateInSelectedNetwork => responses. add ( FrontendMessage :: UpdateInSelectedNetwork {
1667
1684
in_selected_network : selection_network_path == breadcrumb_network_path,
1668
1685
} ) ,
1686
+ NodeGraphMessage :: UpdateHints => {
1687
+ self . update_node_graph_hints ( responses) ;
1688
+ }
1669
1689
NodeGraphMessage :: SendSelectedNodes => {
1670
1690
let Some ( selected_nodes) = network_interface. selected_nodes_in_nested_network ( breadcrumb_network_path) else {
1671
1691
log:: error!( "Could not get selected nodes in NodeGraphMessage::SendSelectedNodes" ) ;
@@ -1751,7 +1771,7 @@ impl NodeGraphMessageHandler {
1751
1771
let mut widgets = vec ! [
1752
1772
PopoverButton :: new( )
1753
1773
. icon( Some ( "Node" . to_string( ) ) )
1754
- . tooltip( "Add a new node " )
1774
+ . tooltip( "New Node (Right Click) " )
1755
1775
. popover_layout( {
1756
1776
let node_chooser = NodeCatalog :: new( )
1757
1777
. on_update( move |node_type| {
@@ -2421,6 +2441,46 @@ impl NodeGraphMessageHandler {
2421
2441
DVec2 :: new( input_position. x, input_position. y) ,
2422
2442
]
2423
2443
}
2444
+
2445
+ pub fn update_node_graph_hints ( & self , responses : & mut VecDeque < Message > ) {
2446
+ // A wire is in progress and its start and end connectors are set
2447
+ let wiring = self . wire_in_progress_from_connector . is_some ( ) ;
2448
+
2449
+ // Node gragging is in progress (having already moved at least one pixel from the mouse down position)
2450
+ let dragging_nodes = self . drag_start . as_ref ( ) . is_some_and ( |( _, dragged) | * dragged) ;
2451
+
2452
+ // A box selection is in progress
2453
+ let dragging_box_selection = self . box_selection_start . is_some_and ( |( _, box_selection_dragged) | box_selection_dragged) ;
2454
+
2455
+ // Cancel the ongoing action
2456
+ if wiring || dragging_nodes || dragging_box_selection {
2457
+ let hint_data = HintData ( vec ! [ HintGroup ( vec![ HintInfo :: mouse( MouseMotion :: Rmb , "" ) , HintInfo :: keys( [ Key :: Escape ] , "Cancel" ) . prepend_slash( ) ] ) ] ) ;
2458
+ responses. add ( FrontendMessage :: UpdateInputHints { hint_data } ) ;
2459
+ return ;
2460
+ }
2461
+
2462
+ // Default hints for all other states
2463
+ let mut hint_data = HintData ( vec ! [
2464
+ HintGroup ( vec![ HintInfo :: mouse( MouseMotion :: Rmb , "Add Node" ) ] ) ,
2465
+ HintGroup ( vec![ HintInfo :: mouse( MouseMotion :: Lmb , "Select Node" ) , HintInfo :: keys( [ Key :: Shift ] , "Extend" ) . prepend_plus( ) ] ) ,
2466
+ HintGroup ( vec![ HintInfo :: mouse( MouseMotion :: LmbDrag , "Select Area" ) , HintInfo :: keys( [ Key :: Shift ] , "Extend" ) . prepend_plus( ) ] ) ,
2467
+ ] ) ;
2468
+ if self . has_selection {
2469
+ hint_data. 0 . extend ( [
2470
+ HintGroup ( vec ! [ HintInfo :: mouse( MouseMotion :: LmbDrag , "Drag Selected" ) ] ) ,
2471
+ HintGroup ( vec ! [ HintInfo :: keys( [ Key :: Delete ] , "Delete Selected" ) , HintInfo :: keys( [ Key :: Control ] , "Keep Children" ) . prepend_plus( ) ] ) ,
2472
+ HintGroup ( vec ! [
2473
+ HintInfo :: keys_and_mouse( [ Key :: Alt ] , MouseMotion :: LmbDrag , "Move Duplicate" ) ,
2474
+ HintInfo :: keys( [ Key :: Control , Key :: KeyD ] , "Duplicate" ) . add_mac_keys( [ Key :: Command , Key :: KeyD ] ) ,
2475
+ ] ) ,
2476
+ ] ) ;
2477
+ }
2478
+ hint_data. 0 . extend ( [
2479
+ HintGroup ( vec ! [ HintInfo :: mouse( MouseMotion :: LmbDouble , "Enter Node Subgraph" ) ] ) ,
2480
+ HintGroup ( vec ! [ HintInfo :: keys_and_mouse( [ Key :: Alt ] , MouseMotion :: Lmb , "Preview Node Output" ) ] ) ,
2481
+ ] ) ;
2482
+ responses. add ( FrontendMessage :: UpdateInputHints { hint_data } ) ;
2483
+ }
2424
2484
}
2425
2485
2426
2486
#[ derive( Default ) ]
@@ -2499,7 +2559,7 @@ impl Default for NodeGraphMessageHandler {
2499
2559
widgets : [ LayoutGroup :: Row { widgets : Vec :: new ( ) } , LayoutGroup :: Row { widgets : Vec :: new ( ) } ] ,
2500
2560
drag_start : None ,
2501
2561
begin_dragging : false ,
2502
- drag_occurred : false ,
2562
+ node_has_moved_in_drag : false ,
2503
2563
shift_without_push : false ,
2504
2564
box_selection_start : None ,
2505
2565
selection_before_pointer_down : Vec :: new ( ) ,
@@ -2527,7 +2587,7 @@ impl PartialEq for NodeGraphMessageHandler {
2527
2587
&& self . widgets == other. widgets
2528
2588
&& self . drag_start == other. drag_start
2529
2589
&& self . begin_dragging == other. begin_dragging
2530
- && self . drag_occurred == other. drag_occurred
2590
+ && self . node_has_moved_in_drag == other. node_has_moved_in_drag
2531
2591
&& self . box_selection_start == other. box_selection_start
2532
2592
&& self . initial_disconnecting == other. initial_disconnecting
2533
2593
&& self . select_if_not_dragged == other. select_if_not_dragged
0 commit comments