Browse Source

Create node at pos and close context menu

flabbet 1 year ago
parent
commit
2a3115b9ba

+ 1 - 1
src/PixiEditor.AvaloniaUI/Styles/Templates/NodeGraphView.axaml

@@ -12,7 +12,7 @@
                             <nodes:NodePicker
                                 AllNodeTypes="{Binding AllNodeTypes, RelativeSource={RelativeSource TemplatedParent}}"
                                 SearchQuery="{Binding SearchQuery, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
-                                SelectNodeCommand="{Binding CreateNodeCommand, RelativeSource={RelativeSource TemplatedParent}}"
+                                SelectNodeCommand="{Binding CreateNodeFromContextCommand, RelativeSource={RelativeSource TemplatedParent}}"
                                 />
                         </Flyout>
                         </Grid.ContextFlyout>

+ 25 - 4
src/PixiEditor.AvaloniaUI/ViewModels/Document/NodeGraphViewModel.cs

@@ -10,6 +10,7 @@ using PixiEditor.ChangeableDocument.Actions.Generated;
 using PixiEditor.ChangeableDocument.Changeables.Graph;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.ChangeableDocument.ChangeInfos;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
 using PixiEditor.Numerics;
 
@@ -190,21 +191,41 @@ internal class NodeGraphViewModel : ViewModelBase, INodeGraphHandler
         Internals.ActionAccumulator.AddFinishedActions(new EndNodePosition_Action());
     }
 
-    public void CreateNode(Type nodeType)
+    public void CreateNode(Type nodeType, VecD pos = default)
     {
         IAction change;
 
         PairNodeAttribute? pairAttribute = nodeType.GetCustomAttribute<PairNodeAttribute>(true);
+        
+        List<IAction> changes = new();
+        
         if (pairAttribute != null)
         {
-            change = new CreateNodePair_Action(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), nodeType);
+            Guid startId = Guid.NewGuid();
+            Guid endId = Guid.NewGuid();
+            changes.Add(new CreateNodePair_Action(startId, endId, Guid.NewGuid(), nodeType));
+            
+            if(pos != default)
+            {
+                changes.Add(new NodePosition_Action(startId, pos));
+                changes.Add(new EndNodePosition_Action());
+                changes.Add(new NodePosition_Action(endId, new VecD(pos.X + 400, pos.Y)));
+                changes.Add(new EndNodePosition_Action()); 
+            }
         }
         else
         {
-            change = new CreateNode_Action(nodeType, Guid.NewGuid());
+            Guid nodeId = Guid.NewGuid();
+            changes.Add(new CreateNode_Action(nodeType, nodeId));
+            
+            if(pos != default)
+            {
+                changes.Add(new NodePosition_Action(nodeId, pos));
+                changes.Add(new EndNodePosition_Action());
+            }
         }
 
-        Internals.ActionAccumulator.AddFinishedActions(change);
+        Internals.ActionAccumulator.AddFinishedActions(changes.ToArray());
     }
 
     public void RemoveNodes(Guid[] selectedNodes)

+ 3 - 3
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/NodeGraphManagerViewModel.cs

@@ -33,11 +33,11 @@ internal class NodeGraphManagerViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Internal("PixiEditor.NodeGraph.CreateNode")]
-    public void CreateNode(Type nodeType)
+    public void CreateNode((Type nodeType, VecD pos) data)
     {
-        Owner.DocumentManagerSubViewModel.ActiveDocument?.NodeGraph.CreateNode(nodeType);
+        Owner.DocumentManagerSubViewModel.ActiveDocument?.NodeGraph.CreateNode(data.nodeType, data.pos);
     }
-
+    
     [Command.Internal("PixiEditor.NodeGraph.ConnectProperties")]
     public void ConnectProperties((INodePropertyHandler input, INodePropertyHandler output) args)
     {

+ 23 - 0
src/PixiEditor.AvaloniaUI/Views/Nodes/NodeGraphView.cs

@@ -70,6 +70,15 @@ internal class NodeGraphView : Zoombox.Zoombox
         AvaloniaProperty.Register<NodeGraphView, ICommand>(
             "ConnectPropertiesCommand");
 
+    public static readonly StyledProperty<ICommand> CreateNodeFromContextCommandProperty = AvaloniaProperty.Register<NodeGraphView, ICommand>(
+        "CreateNodeFromContextCommand");
+
+    public ICommand CreateNodeFromContextCommand
+    {
+        get => GetValue(CreateNodeFromContextCommandProperty);
+        set => SetValue(CreateNodeFromContextCommandProperty, value);
+    }
+
     public ICommand ConnectPropertiesCommand
     {
         get => GetValue(ConnectPropertiesCommandProperty);
@@ -162,6 +171,7 @@ internal class NodeGraphView : Zoombox.Zoombox
     private ConnectionLine _previewConnectionLine;
     private NodeConnectionViewModel? _hiddenConnection;
     private Color _startingPropColor;
+    private VecD _lastMouseClickPos;
 
     public NodeGraphView()
     {
@@ -170,9 +180,19 @@ internal class NodeGraphView : Zoombox.Zoombox
         DraggedCommand = new RelayCommand<PointerEventArgs>(Dragged);
         EndDragCommand = new RelayCommand<PointerCaptureLostEventArgs>(EndDrag);
         SocketDropCommand = new RelayCommand<NodeSocket>(SocketDrop);
+        CreateNodeFromContextCommand = new RelayCommand<Type>(CreateNodeType);
 
         AllNodeTypes = new ObservableCollection<Type>(GatherAssemblyTypes<Node>());
     }
+    
+    private void CreateNodeType(Type nodeType)
+    {
+        if (CreateNodeCommand != null && CreateNodeCommand.CanExecute(nodeType))
+        {
+            CreateNodeCommand.Execute((nodeType, _lastMouseClickPos));
+            ((Control)this.GetVisualDescendants().FirstOrDefault()).ContextFlyout.Hide();
+        }
+    }
 
     protected override void OnPointerPressed(PointerPressedEventArgs e)
     {
@@ -182,6 +202,9 @@ internal class NodeGraphView : Zoombox.Zoombox
         {
             ClearSelection();
         }
+        
+        Point pos = e.GetPosition(this);
+        _lastMouseClickPos = ToZoomboxSpace(new VecD(pos.X, pos.Y));
     }
 
     protected override void OnPointerMoved(PointerEventArgs e)

+ 3 - 6
src/PixiEditor.AvaloniaUI/Views/Nodes/NodePicker.cs

@@ -5,6 +5,8 @@ using Avalonia.Controls;
 using Avalonia.Controls.Primitives;
 using Avalonia.Interactivity;
 using Avalonia.Markup.Xaml;
+using CommunityToolkit.Mvvm.Input;
+using PixiEditor.Numerics;
 
 namespace PixiEditor.AvaloniaUI.Views.Nodes;
 
@@ -46,17 +48,12 @@ public partial class NodePicker : TemplatedControl
         get => GetValue(SelectNodeCommandProperty);
         set => SetValue(SelectNodeCommandProperty, value);
     }
-
+    
     static NodePicker()
     {
         SearchQueryProperty.Changed.Subscribe(OnSearchQueryChanged);
     }
 
-    public NodePicker()
-    {
-
-    }
-
     private static void OnSearchQueryChanged(AvaloniaPropertyChangedEventArgs e)
     {
         if (e.Sender is NodePicker nodePicker)