Browse Source

Added view models for all nodes

CPKreuz 1 year ago
parent
commit
39272c42f2
42 changed files with 466 additions and 136 deletions
  1. 3 0
      src/PixiEditor.ChangeableDocument/ChangeInfos/NodeGraph/NodeMetadata.cs
  2. 30 25
      src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs
  3. 2 2
      src/PixiEditor/Models/Handlers/IDocument.cs
  4. 11 11
      src/PixiEditor/ViewModels/Document/DocumentViewModel.cs
  5. 22 22
      src/PixiEditor/ViewModels/Document/FolderHandlerFactory.cs
  6. 22 22
      src/PixiEditor/ViewModels/Document/LayerHandlerFactory.cs
  7. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/Animable/TimeNodeViewModel.cs
  8. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/CombineChannelsNodeViewModel.cs
  9. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/CombineColorNodeViewModel.cs
  10. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/CombineVecDNodeViewModel.cs
  11. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/CombineVecINodeViewModel.cs
  12. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/SeparateChannelsNodeViewModel.cs
  13. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/SeparateColorNodeViewModel.cs
  14. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/SeparateVecDNodeViewModel.cs
  15. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/SeparateVecINodeViewModel.cs
  16. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/CreateImageNodeViewModel.cs
  17. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/DebugBlendModeNodeViewModel.cs
  18. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/EllipseNodeViewModel.cs
  19. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/FilterNodes/ApplyFilterNodeViewModel.cs
  20. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/FilterNodes/ColorMatrixFilterNodeViewModel.cs
  21. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/FilterNodes/GrayscaleNodeViewModel.cs
  22. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/FilterNodes/KernelFilterNodeViewModel.cs
  23. 7 7
      src/PixiEditor/ViewModels/Document/Nodes/FolderNodeViewModel.cs
  24. 7 10
      src/PixiEditor/ViewModels/Document/Nodes/ImageLayerNodeViewModel.cs
  25. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/LerpColorNodeViewModel.cs
  26. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/MathNodeViewModel.cs
  27. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/MergeNodeViewModel.cs
  28. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/ModifyImageLeftNodeViewModel.cs
  29. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/ModifyImageRightNodeViewModel.cs
  30. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/NoiseNodeViewModel.cs
  31. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/OutputNodeViewModel.cs
  32. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/Points/DistributePointsNodeViewModel.cs
  33. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/Points/RasterizePointsNodeViewModel.cs
  34. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/Points/RemoveClosePointsNodeViewModel.cs
  35. 12 0
      src/PixiEditor/ViewModels/Document/Nodes/SampleImageNodeViewModel.cs
  36. 3 13
      src/PixiEditor/ViewModels/Document/Nodes/StructureMemberViewModel.cs
  37. 22 11
      src/PixiEditor/ViewModels/Nodes/NodeViewModel.cs
  38. 4 4
      src/PixiEditor/ViewModels/SubViewModels/LayersViewModel.cs
  39. 3 3
      src/PixiEditor/Views/Layers/FolderControl.axaml.cs
  40. 3 3
      src/PixiEditor/Views/Layers/LayerControl.axaml.cs
  41. 2 2
      src/PixiEditor/Views/Layers/LayersManager.axaml
  42. 1 1
      src/PixiEditor/Views/Layers/LayersManager.axaml.cs

+ 3 - 0
src/PixiEditor.ChangeableDocument/ChangeInfos/NodeGraph/NodeMetadata.cs

@@ -14,9 +14,12 @@ public class NodeMetadata
     public string? ZoneUniqueName { get; private set; }
     
     public string? Category { get; private set; }
+    
+    public Type NodeType { get; private set; }
 
     public NodeMetadata(Type type)
     {
+        NodeType = type;
         AddAttributes(type);
     }
     

+ 30 - 25
src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs

@@ -1,4 +1,5 @@
 using System.Collections.Immutable;
+using System.Reflection;
 using ChunkyImageLib;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Exceptions;
@@ -56,15 +57,7 @@ internal class DocumentUpdater
         switch (arbitraryInfo)
         {
             case CreateStructureMember_ChangeInfo info:
-                if (info is CreateLayer_ChangeInfo layerChangeInfo)
-                {
-                    ProcessCreateNode<LayerViewModel>(info);
-                }
-                else if (info is CreateFolder_ChangeInfo folderChangeInfo)
-                {
-                    ProcessCreateNode<FolderViewModel>(info);
-                }
-
+                ProcessCreateNode(info);
                 ProcessCreateStructureMember(info);
                 break;
             case DeleteStructureMember_ChangeInfo info:
@@ -171,7 +164,7 @@ internal class DocumentUpdater
                 ClearSelectedKeyFrames(info);
                 break;
             case CreateNode_ChangeInfo info:
-                ProcessCreateNode<NodeViewModel>(info);
+                ProcessCreateNode(info);
                 break;
             case DeleteNode_ChangeInfo info:
                 ProcessDeleteNode(info);
@@ -512,28 +505,40 @@ internal class DocumentUpdater
         doc.AnimationHandler.ClearSelectedKeyFrames();
     }
 
-    private void ProcessCreateNode<T>(CreateNode_ChangeInfo info) where T : NodeViewModel, new()
+    private void ProcessCreateNode(CreateNode_ChangeInfo info)
     {
-        T node = new T()
-        {
-            InternalName = info.InternalName, Id = info.Id, Document = (DocumentViewModel)doc, Internals = helper
-        };
+        var nodeType = info.Metadata.NodeType;
+        
+        var ns = nodeType.Namespace.Replace("PixiEditor.ChangeableDocument.Changeables.Graph.Nodes", "PixiEditor.ViewModels.Document.Nodes");
+        var name = nodeType.Name.Replace("Node", "NodeViewModel");
+        var nodeViewModelType = Type.GetType($"{ns}.{name}");
+
+        var viewModel = (NodeViewModel)Activator.CreateInstance(nodeViewModelType);
 
-        node.SetName(info.NodeName);
-        node.SetPosition(info.Position);
+        InitializeNodeViewModel(info, viewModel);
+    }
 
-        List<INodePropertyHandler> inputs = CreateProperties(info.Inputs, node, true);
-        List<INodePropertyHandler> outputs = CreateProperties(info.Outputs, node, false);
-        node.Inputs.AddRange(inputs);
-        node.Outputs.AddRange(outputs);
-        doc.NodeGraphHandler.AddNode(node);
+    private void InitializeNodeViewModel(CreateNode_ChangeInfo info, NodeViewModel viewModel)
+    {
+        viewModel.Initialize(info.Id, info.InternalName, (DocumentViewModel)doc, helper);
+        
+        viewModel.SetName(info.NodeName);
+        viewModel.SetPosition(info.Position);
+        
+        var inputs = CreateProperties(info.Inputs, viewModel, true);
+        var outputs = CreateProperties(info.Outputs, viewModel, false);
+        viewModel.Inputs.AddRange(inputs);
+        viewModel.Outputs.AddRange(outputs);
+        doc.NodeGraphHandler.AddNode(viewModel);
 
-        node.Metadata = info.Metadata;
+        viewModel.Metadata = info.Metadata;
 
-        AddZoneIfNeeded(info, node);
+        AddZoneIfNeeded(info, viewModel);
+        
+        viewModel.OnInitialized();
     }
 
-    private void AddZoneIfNeeded<T>(CreateNode_ChangeInfo info, T node) where T : NodeViewModel, new()
+    private void AddZoneIfNeeded(CreateNode_ChangeInfo info, NodeViewModel node)
     {
         if (node.Metadata?.PairNodeGuid != null)
         {

+ 2 - 2
src/PixiEditor/Models/Handlers/IDocument.cs

@@ -31,8 +31,8 @@ internal interface IDocument : IHandler
     public bool AllChangesSaved { get; }
     public string CoordinatesString { get; set; }
     public IReadOnlyCollection<IStructureMemberHandler> SoftSelectedStructureMembers { get; }
-    public ILayerHandlerFactory LayerHandlerFactory { get; }
-    public IFolderHandlerFactory FolderHandlerFactory { get; }
+    //public ILayerHandlerFactory LayerHandlerFactory { get; }
+    //public IFolderHandlerFactory FolderHandlerFactory { get; }
     public ITransformHandler TransformHandler { get; }
     public bool Busy { get; set; }
     public ILineOverlayHandler LineToolOverlayHandler { get; }

+ 11 - 11
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -210,8 +210,8 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
     IDocumentOperations IDocument.Operations => Operations;
     ITransformHandler IDocument.TransformHandler => TransformViewModel;
     ILineOverlayHandler IDocument.LineToolOverlayHandler => LineToolOverlayViewModel;
-    public ILayerHandlerFactory LayerHandlerFactory { get; }
-    public IFolderHandlerFactory FolderHandlerFactory { get; }
+    //public ILayerHandlerFactory LayerHandlerFactory { get; }
+    //public IFolderHandlerFactory FolderHandlerFactory { get; }
     IReferenceLayerHandler IDocument.ReferenceLayerHandler => ReferenceLayerViewModel;
     IAnimationHandler IDocument.AnimationHandler => AnimationDataViewModel;
 
@@ -225,8 +225,8 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         EventInlet = new DocumentEventsModule(this, Internals);
         Operations = new DocumentOperationsModule(this, Internals);
 
-        LayerHandlerFactory = new LayerHandlerFactory(this);
-        FolderHandlerFactory = new FolderHandlerFactory(this);
+        //LayerHandlerFactory = new LayerHandlerFactory(this);
+        //FolderHandlerFactory = new FolderHandlerFactory(this);
         AnimationDataViewModel = new(this, Internals);
 
         NodeGraph = new NodeGraphViewModel(this, Internals);
@@ -538,7 +538,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         IStructureMemberHandler? layerToExtractFrom = null)
     {
         layerToExtractFrom ??= SelectedStructureMember;
-        if (layerToExtractFrom is not LayerViewModel layerVm)
+        if (layerToExtractFrom is not ImageLayerNodeViewModel layerVm)
             return new Error();
         if (SelectionPathBindable.IsEmpty)
             return new None();
@@ -668,7 +668,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
                         _ => Colors.Transparent);
             }
 
-            if (SelectedStructureMember is not LayerViewModel layerVm)
+            if (SelectedStructureMember is not ImageLayerNodeViewModel layerVm)
                 return Colors.Transparent;
             IReadOnlyStructureNode? maybeMember = Internals.Tracker.Document.FindMember(layerVm.Id);
             if (maybeMember is not IReadOnlyImageNode layer)
@@ -788,12 +788,12 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
             var foundMember = StructureHelper.Find(member);
             if (foundMember != null)
             {
-                if (foundMember is LayerViewModel layer && selectedMembers.Contains(foundMember.Id) &&
+                if (foundMember is ImageLayerNodeViewModel layer && selectedMembers.Contains(foundMember.Id) &&
                     !result.Contains(layer.Id))
                 {
                     result.Add(layer.Id);
                 }
-                else if (foundMember is FolderViewModel folder && selectedMembers.Contains(foundMember.Id))
+                else if (foundMember is FolderNodeViewModel folder && selectedMembers.Contains(foundMember.Id))
                 {
                     if (includeFoldersWithMask && folder.HasMaskBindable && !result.Contains(folder.Id))
                         result.Add(folder.Id);
@@ -810,16 +810,16 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         OnPropertyChanged(nameof(AllChangesSaved));
     }
 
-    private void ExtractSelectedLayers(FolderViewModel folder, List<Guid> list,
+    private void ExtractSelectedLayers(FolderNodeViewModel folder, List<Guid> list,
         bool includeFoldersWithMask)
     {
         foreach (var member in folder.Children)
         {
-            if (member is LayerViewModel layer && !list.Contains(layer.Id))
+            if (member is ImageLayerNodeViewModel layer && !list.Contains(layer.Id))
             {
                 list.Add(layer.Id);
             }
-            else if (member is FolderViewModel childFolder)
+            else if (member is FolderNodeViewModel childFolder)
             {
                 if (includeFoldersWithMask && childFolder.HasMaskBindable && !list.Contains(childFolder.Id))
                     list.Add(childFolder.Id);

+ 22 - 22
src/PixiEditor/ViewModels/Document/FolderHandlerFactory.cs

@@ -1,22 +1,22 @@
-using PixiEditor.Helpers;
-using PixiEditor.Models.DocumentModels;
-using PixiEditor.Models.Handlers;
-using PixiEditor.ViewModels.Document.Nodes;
-
-namespace PixiEditor.ViewModels.Document;
-
-internal class FolderHandlerFactory : IFolderHandlerFactory
-{
-    public DocumentViewModel Document { get; }
-    IDocument IFolderHandlerFactory.Document => Document;
-
-    public FolderHandlerFactory(DocumentViewModel document)
-    {
-        Document = document;
-    }
-
-    public IFolderHandler CreateFolderHandler(DocumentInternalParts helper, Guid infoGuidValue)
-    {
-        return new FolderViewModel(Document, helper, infoGuidValue);
-    }
-}
+// using PixiEditor.Helpers;
+// using PixiEditor.Models.DocumentModels;
+// using PixiEditor.Models.Handlers;
+// using PixiEditor.ViewModels.Document.Nodes;
+//
+// namespace PixiEditor.ViewModels.Document;
+//
+// internal class FolderHandlerFactory : IFolderHandlerFactory
+// {
+//     public DocumentViewModel Document { get; }
+//     IDocument IFolderHandlerFactory.Document => Document;
+//
+//     public FolderHandlerFactory(DocumentViewModel document)
+//     {
+//         Document = document;
+//     }
+//
+//     public IFolderHandler CreateFolderHandler(DocumentInternalParts helper, Guid infoGuidValue)
+//     {
+//         return new FolderNodeViewModel(Document, helper, infoGuidValue);
+//     }
+// }

+ 22 - 22
src/PixiEditor/ViewModels/Document/LayerHandlerFactory.cs

@@ -1,22 +1,22 @@
-using PixiEditor.Helpers;
-using PixiEditor.Models.DocumentModels;
-using PixiEditor.Models.Handlers;
-using PixiEditor.ViewModels.Document.Nodes;
-
-namespace PixiEditor.ViewModels.Document;
-
-internal class LayerHandlerFactory : ILayerHandlerFactory
-{
-    public DocumentViewModel Document { get; }
-    IDocument ILayerHandlerFactory.Document => Document;
-
-    public LayerHandlerFactory(DocumentViewModel document)
-    {
-        Document = document;
-    }
-
-    public ILayerHandler CreateLayerHandler(DocumentInternalParts helper, Guid infoGuidValue)
-    {
-        return new LayerViewModel(Document, helper, infoGuidValue);
-    }
-}
+// using PixiEditor.Helpers;
+// using PixiEditor.Models.DocumentModels;
+// using PixiEditor.Models.Handlers;
+// using PixiEditor.ViewModels.Document.Nodes;
+//
+// namespace PixiEditor.ViewModels.Document;
+//
+// internal class LayerHandlerFactory : ILayerHandlerFactory
+// {
+//     public DocumentViewModel Document { get; }
+//     IDocument ILayerHandlerFactory.Document => Document;
+//
+//     public LayerHandlerFactory(DocumentViewModel document)
+//     {
+//         Document = document;
+//     }
+//
+//     public ILayerHandler CreateLayerHandler(DocumentInternalParts helper, Guid infoGuidValue)
+//     {
+//         return new ImageLayerNodeViewModel(Document, helper, infoGuidValue);
+//     }
+// }

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/Animable/TimeNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Animable;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.Animable;
+
+internal class TimeNodeViewModel : NodeViewModel<TimeNode>
+{
+    public override LocalizedString DisplayName => "TIME_NODE";
+    
+    public override LocalizedString Category => "ANIMATION";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/CombineChannelsNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.CombineSeparate;
+
+internal class CombineChannelsNodeViewModel : NodeViewModel<CombineChannelsNode>
+{
+    public override LocalizedString DisplayName => "COMBINE_CHANNELS_NODE";
+    
+    public override LocalizedString Category => "IMAGE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/CombineColorNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.CombineSeparate;
+
+internal class CombineColorNodeViewModel : NodeViewModel<CombineColorNode>
+{
+    public override LocalizedString DisplayName => "COMBINE_COLOR_NODE";
+    
+    public override LocalizedString Category => "COLOR";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/CombineVecDNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.CombineSeparate;
+
+internal class CombineVecDNodeViewModel : NodeViewModel<CombineVecDNode>
+{
+    public override LocalizedString DisplayName => "COMBINE_VECD_NODE";
+    
+    public override LocalizedString Category => "NUMBERS";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/CombineVecINodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.CombineSeparate;
+
+internal class CombineVecINodeViewModel : NodeViewModel<CombineVecINode>
+{
+    public override LocalizedString DisplayName => "COMBINE_VECI_NODE";
+    
+    public override LocalizedString Category => "NUMBERS";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/SeparateChannelsNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.CombineSeparate;
+
+internal class SeparateChannelsNodeViewModel : NodeViewModel<SeparateChannelsNode>
+{
+    public override LocalizedString DisplayName => "SEPARATE_CHANNELS_NODE";
+    
+    public override LocalizedString Category => "IMAGE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/SeparateColorNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.CombineSeparate;
+
+internal class SeparateColorNodeViewModel : NodeViewModel<SeparateColorNode>
+{
+    public override LocalizedString DisplayName => "SEPARATE_COLOR_NODE";
+    
+    public override LocalizedString Category => "COLOR";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/SeparateVecDNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.CombineSeparate;
+
+internal class SeparateVecDNodeViewModel : NodeViewModel<SeparateVecDNode>
+{
+    public override LocalizedString DisplayName => "SEPARATE_VECD_NODE";
+    
+    public override LocalizedString Category => "NUMBERS";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/CombineSeparate/SeparateVecINodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.CombineSeparate;
+
+internal class SeparateVecINodeViewModel : NodeViewModel<SeparateVecINode>
+{
+    public override LocalizedString DisplayName => "SEPARATE_VECI_NODE";
+    
+    public override LocalizedString Category => "NUMBERS";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/CreateImageNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class CreateImageNodeViewModel : NodeViewModel<CreateImageNode>
+{
+    public override LocalizedString DisplayName => "CREATE_IMAGE_NODE";
+    
+    public override LocalizedString Category => "IMAGE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/DebugBlendModeNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class DebugBlendModeNodeViewModel : NodeViewModel<DebugBlendModeNode>
+{
+    public override LocalizedString DisplayName { get; } = "Debug Blend Mode";
+
+    public override LocalizedString Category { get; } = "DEBUG";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/EllipseNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class EllipseNodeViewModel : NodeViewModel<EllipseNode>
+{
+    public override LocalizedString DisplayName => "ELLIPSE_NODE";
+    
+    public override LocalizedString Category => "SHAPE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/FilterNodes/ApplyFilterNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.FilterNodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.FilterNodes;
+
+internal class ApplyFilterNodeViewModel : NodeViewModel<ApplyFilterNode>
+{
+    public override LocalizedString DisplayName => "APPLY_FILTER_NODE";
+    
+    public override LocalizedString Category => "FILTERS";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/FilterNodes/ColorMatrixFilterNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.FilterNodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.FilterNodes;
+
+internal class ColorMatrixFilterNodeViewModel : NodeViewModel<ColorMatrixFilterNode>
+{
+    public override LocalizedString DisplayName => "COLOR_MATRIX_TRANSFORM_FILTER_NODE";
+    
+    public override LocalizedString Category => "FILTERS";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/FilterNodes/GrayscaleNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.FilterNodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.FilterNodes;
+
+internal class GrayscaleNodeViewModel : NodeViewModel<GrayscaleNode>
+{
+    public override LocalizedString DisplayName => "GRAYSCALE_FILTER_NODE";
+    
+    public override LocalizedString Category => "FILTERS";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/FilterNodes/KernelFilterNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.FilterNodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.FilterNodes;
+
+internal class KernelFilterNodeViewModel : NodeViewModel<KernelFilterNode>
+{
+    public override LocalizedString DisplayName => "KERNEL_FILTER_NODE";
+    
+    public override LocalizedString Category => "FILTERS";
+}

+ 7 - 7
src/PixiEditor/ViewModels/Document/Nodes/FolderViewModel.cs → src/PixiEditor/ViewModels/Document/Nodes/FolderNodeViewModel.cs

@@ -1,17 +1,17 @@
 using System.Collections.ObjectModel;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Handlers;
 
 namespace PixiEditor.ViewModels.Document.Nodes;
 #nullable enable
-internal class FolderViewModel : StructureMemberViewModel<FolderNode>, IFolderHandler
+internal class FolderNodeViewModel : StructureMemberViewModel<FolderNode>, IFolderHandler
 {
-    public FolderViewModel()
-    {
-        
-    }
-    
     public ObservableCollection<IStructureMemberHandler> Children { get; } = new();
-    public FolderViewModel(DocumentViewModel doc, DocumentInternalParts internals, Guid id) : base(doc, internals, id) { }
+    
+    // Dependent on layer name
+    public override LocalizedString DisplayName => "";
+
+    public override LocalizedString Category => "STRUCTURE";
 }

+ 7 - 10
src/PixiEditor/ViewModels/Document/Nodes/LayerViewModel.cs → src/PixiEditor/ViewModels/Document/Nodes/ImageLayerNodeViewModel.cs

@@ -1,17 +1,13 @@
 using PixiEditor.ChangeableDocument.Actions.Generated;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Handlers;
 
 namespace PixiEditor.ViewModels.Document.Nodes;
-#nullable enable
-internal class LayerViewModel : StructureMemberViewModel<LayerNode>, ILayerHandler
+
+internal class ImageLayerNodeViewModel : StructureMemberViewModel<LayerNode>, ILayerHandler
 {
-    public LayerViewModel()
-    {
-        
-    }
-    
     bool lockTransparency;
     public void SetLockTransparency(bool lockTransparency)
     {
@@ -41,7 +37,8 @@ internal class LayerViewModel : StructureMemberViewModel<LayerNode>, ILayerHandl
         }
     }
 
-    public LayerViewModel(DocumentViewModel doc, DocumentInternalParts internals, Guid id) : base(doc, internals, id)
-    {
-    }
+    // Dependent on layer name
+    public override LocalizedString DisplayName => "";
+
+    public override LocalizedString Category => "STRUCTURE";
 }

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/LerpColorNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class LerpColorNodeViewModel : NodeViewModel<LerpColorNode>
+{
+    public override LocalizedString DisplayName => "LERP_NODE";
+    
+    public override LocalizedString Category => "NUMBERS";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/MathNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class MathNodeViewModel : NodeViewModel<MathNode>
+{
+    public override LocalizedString DisplayName => "MATH_NODE";
+    
+    public override LocalizedString Category => "NUMBERS";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/MergeNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class MergeNodeViewModel : NodeViewModel<MergeNode>
+{
+    public override LocalizedString DisplayName => "MERGE_NODE";
+    
+    public override LocalizedString Category => "IMAGE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/ModifyImageLeftNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class ModifyImageLeftNodeViewModel : NodeViewModel<ModifyImageLeftNode>
+{
+    public override LocalizedString DisplayName => "MODIFY_IMAGE_LEFT_NODE";
+    
+    public override LocalizedString Category => "IMAGE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/ModifyImageRightNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class ModifyImageRightNodeViewModel : NodeViewModel<ModifyImageRightNode>
+{
+    public override LocalizedString DisplayName => "MODIFY_IMAGE_RIGHT_NODE";
+    
+    public override LocalizedString Category => "IMAGE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/NoiseNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class NoiseNodeViewModel : NodeViewModel<NoiseNode>
+{
+    public override LocalizedString DisplayName => "NOISE_NODE";
+    
+    public override LocalizedString Category => "IMAGE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/OutputNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class OutputNodeViewModel : NodeViewModel<OutputNode>
+{
+    public override LocalizedString DisplayName => "OUTPUT_NODE";
+    
+    public override LocalizedString Category => "";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/Points/DistributePointsNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.Points;
+
+internal class DistributePointsNodeViewModel : NodeViewModel<DistributePointsNode>
+{
+    public override LocalizedString DisplayName => "DISTRIBUTE_POINTS";
+    
+    public override LocalizedString Category => "SHAPE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/Points/RasterizePointsNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.Points;
+
+internal class RasterizePointsNodeViewModel : NodeViewModel<RasterizePointsNode>
+{
+    public override LocalizedString DisplayName => "RASTERIZE_POINTS";
+    
+    public override LocalizedString Category => "SHAPE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/Points/RemoveClosePointsNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.Points;
+
+internal class RemoveClosePointsNodeViewModel : NodeViewModel<RemoveClosePointsNode>
+{
+    public override LocalizedString DisplayName => "REMOVE_CLOSE_POINTS";
+    
+    public override LocalizedString Category => "SHAPE";
+}

+ 12 - 0
src/PixiEditor/ViewModels/Document/Nodes/SampleImageNodeViewModel.cs

@@ -0,0 +1,12 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+internal class SampleImageNodeViewModel : NodeViewModel<SampleImageNode>
+{
+    public override LocalizedString DisplayName => "SAMPLE_IMAGE";
+    
+    public override LocalizedString Category => "IMAGE";
+}

+ 3 - 13
src/PixiEditor/ViewModels/Document/Nodes/StructureMemberViewModel.cs

@@ -154,23 +154,13 @@ internal abstract class StructureMemberViewModel<T> : NodeViewModel<T>, IStructu
     }
 
     IDocument IStructureMemberHandler.Document => Document;
-
-    /// <summary>
-    /// Calculates the size of a scaled-down preview for a given size of layer tight bounds.
-    /// </summary>
-
-    public StructureMemberViewModel(DocumentViewModel doc, DocumentInternalParts internals, Guid id)
-    {
-        Document = doc;
-        Internals = internals;
-
-        this.id = id;
-        PreviewSurface = null;
-    }
 }
 
 public static class StructureMemberViewModel
 {
+    /// <summary>
+    /// Calculates the size of a scaled-down preview for a given size of layer tight bounds.
+    /// </summary>
     public static VecI CalculatePreviewSize(VecI tightBoundsSize)
     {
         double proportions = tightBoundsSize.Y / (double)tightBoundsSize.X;

+ 22 - 11
src/PixiEditor/ViewModels/Nodes/NodeViewModel.cs

@@ -18,10 +18,10 @@ using PixiEditor.ViewModels.Document;
 
 namespace PixiEditor.ViewModels.Nodes;
 
-internal class NodeViewModel : ObservableObject, INodeHandler
+internal abstract class NodeViewModel : ObservableObject, INodeHandler
 {
     private IBrush? categoryBrush;
-    private string nodeNameBindable;
+    private string? nodeNameBindable;
     private VecD position;
     private ObservableRangeCollection<INodePropertyHandler> inputs = new();
     private ObservableRangeCollection<INodePropertyHandler> outputs = new();
@@ -30,15 +30,17 @@ internal class NodeViewModel : ObservableObject, INodeHandler
 
     protected Guid id;
 
-    public Guid Id
-    {
-        get => id;
-        init => id = value;
-    }
+    public Guid Id { get => id; private set => id = value; }
+    
+    public abstract LocalizedString DisplayName { get; }
+    
+    public abstract LocalizedString Category { get; }
+
+    public virtual LocalizedString? PickerName { get; }
 
     public string NodeNameBindable
     {
-        get => nodeNameBindable;
+        get => nodeNameBindable ?? DisplayName;
         set
         {
             if (!Document.UpdateableChangeActive)
@@ -49,7 +51,7 @@ internal class NodeViewModel : ObservableObject, INodeHandler
         } 
     }
 
-    public string InternalName { get; init; }
+    public string InternalName { get; private set; }
 
     public IBrush CategoryBackgroundBrush
     {
@@ -110,9 +112,18 @@ internal class NodeViewModel : ObservableObject, INodeHandler
         set => SetProperty(ref isSelected, value);
     }
 
-    internal DocumentViewModel Document { get; init; }
-    internal DocumentInternalParts Internals { get; init; }
+    internal DocumentViewModel Document { get; private set; }
+    internal DocumentInternalParts Internals { get; private set; }
+
+    public void Initialize(Guid id, string internalName, DocumentViewModel document, DocumentInternalParts internals)
+    {
+        Id = id;
+        InternalName = internalName;
+        Document = document;
+        Internals = internals;
+    }
     
+    public virtual void OnInitialized() { }
     
     public NodeViewModel()
     {

+ 4 - 4
src/PixiEditor/ViewModels/SubViewModels/LayersViewModel.cs

@@ -132,7 +132,7 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
     public void ToggleLockTransparency()
     {
         var member = Owner.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember;
-        if (member is not LayerViewModel layerVm)
+        if (member is not ImageLayerNodeViewModel layerVm)
             return;
         layerVm.LockTransparencyBindable = !layerVm.LockTransparencyBindable;
     }
@@ -172,7 +172,7 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
     public void DuplicateLayer()
     {
         var member = Owner.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember;
-        if (member is not LayerViewModel layerVM)
+        if (member is not ImageLayerNodeViewModel layerVM)
             return;
         member.Document.Operations.DuplicateLayer(member.Id);
     }
@@ -181,7 +181,7 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
     public bool SelectedMemberIsLayer(object property)
     {
         var member = Owner.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember;
-        return member is LayerViewModel;
+        return member is ImageLayerNodeViewModel;
     }
 
     private bool HasSelectedMember(bool above)
@@ -207,7 +207,7 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
         var path = doc!.StructureHelper.FindPath(member.Id);
         if (path.Count < 2)
             return;
-        var parent = (FolderViewModel)path[1];
+        var parent = (FolderNodeViewModel)path[1];
         int curIndex = parent.Children.IndexOf(path[0]);
         if (upwards)
         {

+ 3 - 3
src/PixiEditor/Views/Layers/FolderControl.axaml.cs

@@ -13,10 +13,10 @@ namespace PixiEditor.Views.Layers;
 internal partial class FolderControl : UserControl
 {
 
-    public static readonly StyledProperty<FolderViewModel> FolderProperty =
-        AvaloniaProperty.Register<FolderControl, FolderViewModel>(nameof(Folder));
+    public static readonly StyledProperty<FolderNodeViewModel> FolderProperty =
+        AvaloniaProperty.Register<FolderControl, FolderNodeViewModel>(nameof(Folder));
 
-    public FolderViewModel Folder
+    public FolderNodeViewModel Folder
     {
         get => GetValue(FolderProperty);
         set => SetValue(FolderProperty, value);

+ 3 - 3
src/PixiEditor/Views/Layers/LayerControl.axaml.cs

@@ -15,10 +15,10 @@ internal partial class LayerControl : UserControl
 {
     public static string? LayerControlDataName = typeof(LayerControl).FullName;
 
-    public static readonly StyledProperty<LayerViewModel> LayerProperty =
-        AvaloniaProperty.Register<LayerControl, LayerViewModel>(nameof(Layer));
+    public static readonly StyledProperty<ImageLayerNodeViewModel> LayerProperty =
+        AvaloniaProperty.Register<LayerControl, ImageLayerNodeViewModel>(nameof(Layer));
 
-    public LayerViewModel Layer
+    public ImageLayerNodeViewModel Layer
     {
         get => GetValue(LayerProperty);
         set => SetValue(LayerProperty, value);

+ 2 - 2
src/PixiEditor/Views/Layers/LayersManager.axaml

@@ -138,14 +138,14 @@
 
                 </TreeView.Resources>
                 <TreeView.DataTemplates>
-                    <TreeDataTemplate DataType="nodes:FolderViewModel" ItemsSource="{Binding Children}">
+                    <TreeDataTemplate DataType="nodes:FolderNodeViewModel" ItemsSource="{Binding Children}">
                         <layers:FolderControl
                                 Folder="{Binding}"
                                 Manager="{Binding ElementName=layersManager}"
                                 PointerPressed="FolderControl_MouseDown"
                                 PointerReleased="FolderControl_MouseUp"/>
                     </TreeDataTemplate>
-                    <DataTemplate DataType="{x:Type nodes:LayerViewModel}">
+                    <DataTemplate DataType="{x:Type nodes:ImageLayerNodeViewModel}">
                         <layers:LayerControl
                             Layer="{Binding}"
                             Manager="{Binding ElementName=layersManager}"

+ 1 - 1
src/PixiEditor/Views/Layers/LayersManager.axaml.cs

@@ -228,7 +228,7 @@ internal partial class LayersManager : UserControl
         var reversed = root.Reverse();
         foreach (var child in reversed)
         {
-            if (child is FolderViewModel innerFolder)
+            if (child is FolderNodeViewModel innerFolder)
             {
                 matches = TraverseRange(bound1, bound2, innerFolder.Children, action, matches);
             }