Browse Source

Merge pull request #630 from PixiEditor/better-categories

Better Node categories
Krzysztof Krysiński 11 months ago
parent
commit
0c180d0f8a
21 changed files with 118 additions and 24 deletions
  1. 1 2
      src/PixiEditor.ChangeableDocument/ChangeInfos/NodeGraph/CreateNode_ChangeInfo.cs
  2. 27 3
      src/PixiEditor.ChangeableDocument/ChangeInfos/NodeGraph/NodeMetadata.cs
  3. 5 3
      src/PixiEditor.ChangeableDocument/ChangeInfos/Structure/CreateFolder_ChangeInfo.cs
  4. 5 3
      src/PixiEditor.ChangeableDocument/ChangeInfos/Structure/CreateLayer_ChangeInfo.cs
  5. 3 2
      src/PixiEditor.ChangeableDocument/ChangeInfos/Structure/CreateStructureMember_ChangeInfo.cs
  6. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecDNode.cs
  7. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecINode.cs
  8. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateVecDNode.cs
  9. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateVecINode.cs
  10. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MergeNode.cs
  11. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageRightNode.cs
  12. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/NoiseNode.cs
  13. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Points/DistributePointsNode.cs
  14. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Points/RasterizePointsNode.cs
  15. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Points/RemoveClosePointsNode.cs
  16. 32 0
      src/PixiEditor.UI.Common/Accents/Base.axaml
  17. 2 0
      src/PixiEditor/Models/Handlers/INodeHandler.cs
  18. 1 0
      src/PixiEditor/Styles/Templates/NodeGraphView.axaml
  19. 1 1
      src/PixiEditor/Styles/Templates/NodeView.axaml
  20. 21 0
      src/PixiEditor/ViewModels/Nodes/NodeViewModel.cs
  21. 10 0
      src/PixiEditor/Views/Nodes/NodeView.cs

+ 1 - 2
src/PixiEditor.ChangeableDocument/ChangeInfos/NodeGraph/CreateNode_ChangeInfo.cs

@@ -55,8 +55,7 @@ public record CreateNode_ChangeInfo(
             pairNodeGuid = pairNode.OtherNode;
             pairNodeGuid = pairNode.OtherNode;
         }
         }
         
         
-        NodeMetadata metadata = new NodeMetadata() { PairNodeGuid = pairNodeGuid };
-        metadata.AddAttributes(node);
+        NodeMetadata metadata = new NodeMetadata(node) { PairNodeGuid = pairNodeGuid };
 
 
         return new CreateNode_ChangeInfo(internalName, node.DisplayName, node.Position,
         return new CreateNode_ChangeInfo(internalName, node.DisplayName, node.Position,
             node.Id,
             node.Id,

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

@@ -12,11 +12,35 @@ public class NodeMetadata
 
 
     public Guid? PairNodeGuid { get; set; }
     public Guid? PairNodeGuid { get; set; }
     public string? ZoneUniqueName { get; private set; }
     public string? ZoneUniqueName { get; private set; }
+    
+    public string? Category { get; private set; }
 
 
-    public void AddAttributes(IReadOnlyNode node)
+    public NodeMetadata(Type type)
     {
     {
-        Type type = node.GetType();
-        PairNodeAttribute? attribute = type.GetCustomAttribute<PairNodeAttribute>();
+        AddAttributes(type);
+    }
+    
+    public NodeMetadata(IReadOnlyNode node) : this(node.GetType()) { }
+
+    private void AddAttributes(Type type)
+    {
+        AddNodeInfoAttribute(type);
+        AddPairAttributes(type);
+    }
+
+    private void AddNodeInfoAttribute(Type type)
+    {
+        var attribute = type.GetCustomAttribute<NodeInfoAttribute>();
+
+        if (attribute == null)
+            return;
+
+        Category = attribute.Category;
+    }
+
+    private void AddPairAttributes(Type type)
+    {
+        var attribute = type.GetCustomAttribute<PairNodeAttribute>();
 
 
         if (attribute == null)
         if (attribute == null)
             return;
             return;

+ 5 - 3
src/PixiEditor.ChangeableDocument/ChangeInfos/Structure/CreateFolder_ChangeInfo.cs

@@ -18,9 +18,10 @@ public record class CreateFolder_ChangeInfo : CreateStructureMember_ChangeInfo
         bool hasMask,
         bool hasMask,
         bool maskIsVisible,
         bool maskIsVisible,
         ImmutableArray<NodePropertyInfo> Inputs,
         ImmutableArray<NodePropertyInfo> Inputs,
-        ImmutableArray<NodePropertyInfo> Outputs
+        ImmutableArray<NodePropertyInfo> Outputs,
+        NodeMetadata metadata
     ) : base(internalName, opacity, isVisible, clipToMemberBelow, name, blendMode, guidValue, hasMask,
     ) : base(internalName, opacity, isVisible, clipToMemberBelow, name, blendMode, guidValue, hasMask,
-        maskIsVisible, Inputs, Outputs)
+        maskIsVisible, Inputs, Outputs, metadata)
     {
     {
     }
     }
 
 
@@ -36,6 +37,7 @@ public record class CreateFolder_ChangeInfo : CreateStructureMember_ChangeInfo
             folder.Id,
             folder.Id,
             folder.Mask.Value is not null,
             folder.Mask.Value is not null,
             folder.MaskIsVisible.Value, CreatePropertyInfos(folder.InputProperties, true, folder.Id),
             folder.MaskIsVisible.Value, CreatePropertyInfos(folder.InputProperties, true, folder.Id),
-            CreatePropertyInfos(folder.OutputProperties, false, folder.Id));
+            CreatePropertyInfos(folder.OutputProperties, false, folder.Id),
+            new NodeMetadata(folder));
     }
     }
 }
 }

+ 5 - 3
src/PixiEditor.ChangeableDocument/ChangeInfos/Structure/CreateLayer_ChangeInfo.cs

@@ -21,9 +21,10 @@ public record class CreateLayer_ChangeInfo : CreateStructureMember_ChangeInfo
         bool maskIsVisible,
         bool maskIsVisible,
         bool lockTransparency,
         bool lockTransparency,
         ImmutableArray<NodePropertyInfo> inputs,
         ImmutableArray<NodePropertyInfo> inputs,
-        ImmutableArray<NodePropertyInfo> outputs) :
+        ImmutableArray<NodePropertyInfo> outputs,
+        NodeMetadata metadata) :
         base(internalName, opacity, isVisible, clipToMemberBelow, name, blendMode, guidValue, hasMask,
         base(internalName, opacity, isVisible, clipToMemberBelow, name, blendMode, guidValue, hasMask,
-            maskIsVisible, inputs, outputs)
+            maskIsVisible, inputs, outputs, metadata)
     {
     {
         LockTransparency = lockTransparency;
         LockTransparency = lockTransparency;
     }
     }
@@ -44,7 +45,8 @@ public record class CreateLayer_ChangeInfo : CreateStructureMember_ChangeInfo
             layer.MaskIsVisible.Value,
             layer.MaskIsVisible.Value,
             layer is ITransparencyLockable { LockTransparency: true },
             layer is ITransparencyLockable { LockTransparency: true },
             CreatePropertyInfos(layer.InputProperties, true, layer.Id),
             CreatePropertyInfos(layer.InputProperties, true, layer.Id),
-            CreatePropertyInfos(layer.OutputProperties, false, layer.Id)
+            CreatePropertyInfos(layer.OutputProperties, false, layer.Id),
+            new NodeMetadata(layer.GetType())
         );
         );
     }
     }
 }
 }

+ 3 - 2
src/PixiEditor.ChangeableDocument/ChangeInfos/Structure/CreateStructureMember_ChangeInfo.cs

@@ -17,8 +17,9 @@ public abstract record class CreateStructureMember_ChangeInfo(
     bool HasMask,
     bool HasMask,
     bool MaskIsVisible,
     bool MaskIsVisible,
     ImmutableArray<NodePropertyInfo> InputProperties,
     ImmutableArray<NodePropertyInfo> InputProperties,
-    ImmutableArray<NodePropertyInfo> OutputProperties
-) : CreateNode_ChangeInfo(InternalName, Name, new VecD(0, 0), Id, InputProperties, OutputProperties, null)
+    ImmutableArray<NodePropertyInfo> OutputProperties,
+    NodeMetadata Metadata
+) : CreateNode_ChangeInfo(InternalName, Name, new VecD(0, 0), Id, InputProperties, OutputProperties, Metadata)
 {
 {
     public ImmutableArray<NodePropertyInfo> InputProperties { get; init; } = InputProperties;
     public ImmutableArray<NodePropertyInfo> InputProperties { get; init; } = InputProperties;
     public ImmutableArray<NodePropertyInfo> OutputProperties { get; init; } = OutputProperties;
     public ImmutableArray<NodePropertyInfo> OutputProperties { get; init; } = OutputProperties;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecDNode.cs

@@ -7,7 +7,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 
 
-[NodeInfo("CombineVecD", "COMBINE_VECD_NODE", Category = "NUMBER")]
+[NodeInfo("CombineVecD", "COMBINE_VECD_NODE", Category = "NUMBERS")]
 public class CombineVecDNode : Node
 public class CombineVecDNode : Node
 {
 {
     public FuncOutputProperty<Float2> Vector { get; }
     public FuncOutputProperty<Float2> Vector { get; }

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecINode.cs

@@ -6,7 +6,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 
 
-[NodeInfo("CombineVecI", "COMBINE_VECI_NODE", Category = "NUMBER")]
+[NodeInfo("CombineVecI", "COMBINE_VECI_NODE", Category = "NUMBERS")]
 public class CombineVecINode : Node
 public class CombineVecINode : Node
 {
 {
     public FuncOutputProperty<Int2> Vector { get; }
     public FuncOutputProperty<Int2> Vector { get; }

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateVecDNode.cs

@@ -6,7 +6,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 
 
-[NodeInfo("SeparateVecD", "SEPARATE_VECD_NODE", Category = "NUMBER")]
+[NodeInfo("SeparateVecD", "SEPARATE_VECD_NODE", Category = "NUMBERS")]
 public class SeparateVecDNode : Node
 public class SeparateVecDNode : Node
 {
 {
     public FuncInputProperty<Float2> Vector { get; }
     public FuncInputProperty<Float2> Vector { get; }

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateVecINode.cs

@@ -5,7 +5,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 
 
-[NodeInfo("SeparateVecI", "SEPARATE_VECI_NODE", Category = "NUMBER")]
+[NodeInfo("SeparateVecI", "SEPARATE_VECI_NODE", Category = "NUMBERS")]
 public class SeparateVecINode : Node
 public class SeparateVecINode : Node
 {
 {
     public FuncInputProperty<Int2> Vector { get; }
     public FuncInputProperty<Int2> Vector { get; }

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MergeNode.cs

@@ -8,7 +8,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
 
-[NodeInfo("Merge", "MERGE_NODE", Category = "OPERATIONS")]
+[NodeInfo("Merge", "MERGE_NODE", Category = "IMAGE")]
 public class MergeNode : Node, IBackgroundInput
 public class MergeNode : Node, IBackgroundInput
 {
 {
     private Paint _paint = new();
     private Paint _paint = new();

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageRightNode.cs

@@ -14,7 +14,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
 
-[NodeInfo("ModifyImageRight", "MODIFY_IMAGE_RIGHT_NODE", PickerName = "")]
+[NodeInfo("ModifyImageRight", "MODIFY_IMAGE_RIGHT_NODE", PickerName = "", Category = "IMAGE")]
 [PairNode(typeof(ModifyImageLeftNode), "ModifyImageZone")]
 [PairNode(typeof(ModifyImageLeftNode), "ModifyImageZone")]
 public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
 public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
 {
 {

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/NoiseNode.cs

@@ -9,7 +9,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
 
-[NodeInfo("Noise", "NOISE_NODE", Category = "GENERATION")]
+[NodeInfo("Noise", "NOISE_NODE", Category = "IMAGE")]
 public class NoiseNode : Node
 public class NoiseNode : Node
 {
 {
     private double previousScale = double.NaN;
     private double previousScale = double.NaN;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Points/DistributePointsNode.cs

@@ -5,7 +5,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
 
 
-[NodeInfo("DistributePoints", "DISTRIBUTE_POINTS", Category = "GENERATION")]
+[NodeInfo("DistributePoints", "DISTRIBUTE_POINTS", Category = "SHAPE")]
 public class DistributePointsNode : Node
 public class DistributePointsNode : Node
 {
 {
     public OutputProperty<PointList> Points { get; }
     public OutputProperty<PointList> Points { get; }

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Points/RasterizePointsNode.cs

@@ -10,7 +10,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
 
 
-[NodeInfo("RasterizePoints", "RASTERIZE_POINTS", Category = "IMAGE")]
+[NodeInfo("RasterizePoints", "RASTERIZE_POINTS", Category = "SHAPE")]
 public class RasterizePointsNode : Node
 public class RasterizePointsNode : Node
 {
 {
     private Paint _paint = new() { Color = Colors.White };
     private Paint _paint = new() { Color = Colors.White };

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Points/RemoveClosePointsNode.cs

@@ -4,7 +4,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
 
 
-[NodeInfo("RemoveClosePoints", "REMOVE_CLOSE_POINTS", Category = "OPERATIONS")]
+[NodeInfo("RemoveClosePoints", "REMOVE_CLOSE_POINTS", Category = "SHAPE")]
 public class RemoveClosePointsNode : Node
 public class RemoveClosePointsNode : Node
 {
 {
     public OutputProperty<PointList> Output { get; }
     public OutputProperty<PointList> Output { get; }

+ 32 - 0
src/PixiEditor.UI.Common/Accents/Base.axaml

@@ -38,8 +38,14 @@
 
 
             <Color x:Key="NotificationCardBackgroundColor">#303030</Color>
             <Color x:Key="NotificationCardBackgroundColor">#303030</Color>
             
             
+            <!--                          -->
+            <!--     <| Node Colors |>    -->
+            <!--                          -->
+            
+            <!-- Sockets -->
             <Color x:Key="DefaultSocketColor">#c0334e</Color>
             <Color x:Key="DefaultSocketColor">#c0334e</Color>
             <Color x:Key="ImageSocketColor">#99c47a</Color>
             <Color x:Key="ImageSocketColor">#99c47a</Color>
+            <Color x:Key="FilterSocketColor">#CC5C5C</Color>
             <Color x:Key="BoolSocketColor">#68abdf</Color>
             <Color x:Key="BoolSocketColor">#68abdf</Color>
             <Color x:Key="FloatSocketColor">#ffc66d</Color>
             <Color x:Key="FloatSocketColor">#ffc66d</Color>
             <Color x:Key="DoubleSocketColor">#efb66d</Color>
             <Color x:Key="DoubleSocketColor">#efb66d</Color>
@@ -49,6 +55,7 @@
             <Color x:Key="IntSocketColor">#4C64B1</Color>
             <Color x:Key="IntSocketColor">#4C64B1</Color>
             <Color x:Key="PointListSocketColor">#7f5280</Color>
             <Color x:Key="PointListSocketColor">#7f5280</Color>
             
             
+            <!-- Zones & Frames -->
             <Color x:Key="PixiEditorModifyImageBorderColor">#68abdf</Color>
             <Color x:Key="PixiEditorModifyImageBorderColor">#68abdf</Color>
             <Color x:Key="PixiEditorModifyImageNodeBackgroundColor">#4068abdf</Color>
             <Color x:Key="PixiEditorModifyImageNodeBackgroundColor">#4068abdf</Color>
 
 
@@ -57,6 +64,15 @@
 
 
             <Color x:Key="NodeFrameBorderColor">#101010</Color>
             <Color x:Key="NodeFrameBorderColor">#101010</Color>
             <Color x:Key="NodeFrameBackgroundColor">#40101010</Color>
             <Color x:Key="NodeFrameBackgroundColor">#40101010</Color>
+            
+            <!-- Categories -->
+            <Color x:Key="ImageCategoryBackgroundColor">#5B7348</Color>
+            <Color x:Key="StructureCategoryBackgroundColor">#735C39</Color>
+            <Color x:Key="FiltersCategoryBackgroundColor">#733535</Color>
+            <Color x:Key="ShapeCategoryBackgroundColor">#654266</Color>
+            <Color x:Key="NumbersCategoryBackgroundColor">#666666</Color>
+            <Color x:Key="ColorCategoryBackgroundColor">#3B665D</Color>
+            <Color x:Key="AnimationCategoryBackgroundColor">#4D4466</Color>
 
 
             <system:Double x:Key="ThemeDisabledOpacity">0.4</system:Double>
             <system:Double x:Key="ThemeDisabledOpacity">0.4</system:Double>
 
 
@@ -92,8 +108,14 @@
             
             
             <SolidColorBrush x:Key="SelectionFillBrush" Color="{StaticResource SelectionFillColor}"/>
             <SolidColorBrush x:Key="SelectionFillBrush" Color="{StaticResource SelectionFillColor}"/>
             
             
+            <!--                           -->
+            <!--     <| Node Brushes |>    -->
+            <!--                           -->
+            
+            <!-- Sockets -->
             <SolidColorBrush x:Key="DefaultSocketBrush" Color="{StaticResource DefaultSocketColor}"/>
             <SolidColorBrush x:Key="DefaultSocketBrush" Color="{StaticResource DefaultSocketColor}"/>
             <SolidColorBrush x:Key="TextureSocketBrush" Color="{StaticResource ImageSocketColor}"/>
             <SolidColorBrush x:Key="TextureSocketBrush" Color="{StaticResource ImageSocketColor}"/>
+            <SolidColorBrush x:Key="FilterSocketBrush" Color="{StaticResource FilterSocketColor}"/>
             <SolidColorBrush x:Key="TextureSamplerSocketBrush" Color="{StaticResource ImageSocketColor}"/>
             <SolidColorBrush x:Key="TextureSamplerSocketBrush" Color="{StaticResource ImageSocketColor}"/>
             <SolidColorBrush x:Key="BooleanSocketBrush" Color="{StaticResource BoolSocketColor}"/>
             <SolidColorBrush x:Key="BooleanSocketBrush" Color="{StaticResource BoolSocketColor}"/>
             <SolidColorBrush x:Key="SingleSocketBrush" Color="{StaticResource FloatSocketColor}"/>
             <SolidColorBrush x:Key="SingleSocketBrush" Color="{StaticResource FloatSocketColor}"/>
@@ -109,6 +131,7 @@
             <SolidColorBrush x:Key="Int1SocketBrush" Color="{StaticResource IntSocketColor}"/>
             <SolidColorBrush x:Key="Int1SocketBrush" Color="{StaticResource IntSocketColor}"/>
             <SolidColorBrush x:Key="PointListSocketBrush" Color="{StaticResource PointListSocketColor}"/>
             <SolidColorBrush x:Key="PointListSocketBrush" Color="{StaticResource PointListSocketColor}"/>
             
             
+            <!-- Zones & Frames -->
             <SolidColorBrush x:Key="PixiEditorModifyImageLeftBorderBrush" Color="{StaticResource PixiEditorModifyImageBorderColor}"/>
             <SolidColorBrush x:Key="PixiEditorModifyImageLeftBorderBrush" Color="{StaticResource PixiEditorModifyImageBorderColor}"/>
             <SolidColorBrush x:Key="PixiEditorModifyImageRightBorderBrush" Color="{StaticResource PixiEditorModifyImageBorderColor}"/>
             <SolidColorBrush x:Key="PixiEditorModifyImageRightBorderBrush" Color="{StaticResource PixiEditorModifyImageBorderColor}"/>
             <SolidColorBrush x:Key="PixiEditorModifyImageZoneBorderBrush" Color="{StaticResource PixiEditorModifyImageBorderColor}"/>
             <SolidColorBrush x:Key="PixiEditorModifyImageZoneBorderBrush" Color="{StaticResource PixiEditorModifyImageBorderColor}"/>
@@ -121,6 +144,15 @@
 
 
             <SolidColorBrush x:Key="NodeFrameBorderBrush" Color="{StaticResource NodeFrameBorderColor}"/>
             <SolidColorBrush x:Key="NodeFrameBorderBrush" Color="{StaticResource NodeFrameBorderColor}"/>
             <SolidColorBrush x:Key="NodeFrameBackgroundBrush" Color="{StaticResource NodeFrameBackgroundColor}"/>
             <SolidColorBrush x:Key="NodeFrameBackgroundBrush" Color="{StaticResource NodeFrameBackgroundColor}"/>
+            
+            <!-- Categories -->
+            <SolidColorBrush x:Key="ImageCategoryBackgroundBrush" Color="{StaticResource ImageCategoryBackgroundColor}" />
+            <SolidColorBrush x:Key="StructureCategoryBackgroundBrush" Color="{StaticResource StructureCategoryBackgroundColor}" />
+            <SolidColorBrush x:Key="FiltersCategoryBackgroundBrush" Color="{StaticResource FiltersCategoryBackgroundColor}" />
+            <SolidColorBrush x:Key="ShapeCategoryBackgroundBrush" Color="{StaticResource ShapeCategoryBackgroundColor}" />
+            <SolidColorBrush x:Key="NumbersCategoryBackgroundBrush" Color="{StaticResource NumbersCategoryBackgroundColor}" />
+            <SolidColorBrush x:Key="ColorCategoryBackgroundBrush" Color="{StaticResource ColorCategoryBackgroundColor}" />
+            <SolidColorBrush x:Key="AnimationCategoryBackgroundBrush" Color="{StaticResource AnimationCategoryBackgroundColor}" />
 
 
             <CornerRadius x:Key="ControlCornerRadius">5</CornerRadius>
             <CornerRadius x:Key="ControlCornerRadius">5</CornerRadius>
             <CornerRadius x:Key="ControlCornerRadiusTop">5, 5, 0, 0</CornerRadius>
             <CornerRadius x:Key="ControlCornerRadiusTop">5, 5, 0, 0</CornerRadius>

+ 2 - 0
src/PixiEditor/Models/Handlers/INodeHandler.cs

@@ -1,5 +1,6 @@
 using System.Collections.ObjectModel;
 using System.Collections.ObjectModel;
 using System.ComponentModel;
 using System.ComponentModel;
+using Avalonia.Media;
 using ChunkyImageLib;
 using ChunkyImageLib;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
@@ -13,6 +14,7 @@ public interface INodeHandler : INotifyPropertyChanged
 {
 {
     public Guid Id { get; }
     public Guid Id { get; }
     public string NodeNameBindable { get; set; }
     public string NodeNameBindable { get; set; }
+    public IBrush CategoryBackgroundBrush { get; }
     public string InternalName { get; }
     public string InternalName { get; }
     public NodeMetadata Metadata { get; set; }
     public NodeMetadata Metadata { get; set; }
     public ObservableRangeCollection<INodePropertyHandler> Inputs { get; }
     public ObservableRangeCollection<INodePropertyHandler> Inputs { get; }

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

@@ -39,6 +39,7 @@
                                     <nodes:NodeView
                                     <nodes:NodeView
                                         Node="{Binding}"
                                         Node="{Binding}"
                                         DisplayName="{Binding NodeNameBindable}"
                                         DisplayName="{Binding NodeNameBindable}"
+                                        CategoryBackgroundBrush="{Binding CategoryBackgroundBrush}"
                                         Inputs="{Binding Inputs}"
                                         Inputs="{Binding Inputs}"
                                         BorderBrush="{Binding InternalName, Converter={converters:NodeInternalNameToStyleConverter}, ConverterParameter='BorderBrush'}"
                                         BorderBrush="{Binding InternalName, Converter={converters:NodeInternalNameToStyleConverter}, ConverterParameter='BorderBrush'}"
                                         BorderThickness="2"
                                         BorderThickness="2"

+ 1 - 1
src/PixiEditor/Styles/Templates/NodeView.axaml

@@ -30,7 +30,7 @@
                             </Grid.RowDefinitions>
                             </Grid.RowDefinitions>
                             <Border Padding="{TemplateBinding Padding}" Grid.ColumnSpan="3" Grid.Row="0"
                             <Border Padding="{TemplateBinding Padding}" Grid.ColumnSpan="3" Grid.Row="0"
                                     CornerRadius="4.5, 4.5, 0 ,0"
                                     CornerRadius="4.5, 4.5, 0 ,0"
-                                    Background="{DynamicResource ThemeControlHighBrush}">
+                                    Background="{TemplateBinding CategoryBackgroundBrush}">
                                 <TextBlock ui:Translator.Key="{TemplateBinding DisplayName}"
                                 <TextBlock ui:Translator.Key="{TemplateBinding DisplayName}"
                                            FontWeight="Bold" />
                                            FontWeight="Bold" />
                             </Border>
                             </Border>

+ 21 - 0
src/PixiEditor/ViewModels/Nodes/NodeViewModel.cs

@@ -1,5 +1,6 @@
 using System.Collections.ObjectModel;
 using System.Collections.ObjectModel;
 using Avalonia;
 using Avalonia;
+using Avalonia.Media;
 using ChunkyImageLib;
 using ChunkyImageLib;
 using CommunityToolkit.Mvvm.ComponentModel;
 using CommunityToolkit.Mvvm.ComponentModel;
 using PixiEditor.ChangeableDocument.Actions.Generated;
 using PixiEditor.ChangeableDocument.Actions.Generated;
@@ -17,6 +18,7 @@ using PixiEditor.ViewModels.Document;
 namespace PixiEditor.ViewModels.Nodes;
 namespace PixiEditor.ViewModels.Nodes;
 internal class NodeViewModel : ObservableObject, INodeHandler
 internal class NodeViewModel : ObservableObject, INodeHandler
 {
 {
+    private IBrush? categoryBrush;
     private string nodeNameBindable;
     private string nodeNameBindable;
     private VecD position;
     private VecD position;
     private ObservableRangeCollection<INodePropertyHandler> inputs = new();
     private ObservableRangeCollection<INodePropertyHandler> inputs = new();
@@ -46,6 +48,25 @@ internal class NodeViewModel : ObservableObject, INodeHandler
     }
     }
 
 
     public string InternalName { get; init; }
     public string InternalName { get; init; }
+
+    public IBrush CategoryBackgroundBrush
+    {
+        get
+        {
+            if (categoryBrush == null)
+            {
+                if (Metadata?.Category != null && Application.Current.Styles.TryGetResource($"{Stylize(Metadata.Category)}CategoryBackgroundBrush", App.Current.ActualThemeVariant, out var brushObj) && brushObj is IBrush brush)
+                {
+                    categoryBrush = brush;
+                }
+
+            }
+
+            return categoryBrush;
+
+            string Stylize(string input) => string.Concat(input[0].ToString().ToUpper(), input.ToLower().AsSpan(1));
+        }
+    }
     
     
     public NodeMetadata? Metadata { get; set; }
     public NodeMetadata? Metadata { get; set; }
 
 

+ 10 - 0
src/PixiEditor/Views/Nodes/NodeView.cs

@@ -5,6 +5,7 @@ using Avalonia.Controls;
 using Avalonia.Controls.Metadata;
 using Avalonia.Controls.Metadata;
 using Avalonia.Controls.Primitives;
 using Avalonia.Controls.Primitives;
 using Avalonia.Input;
 using Avalonia.Input;
+using Avalonia.Media;
 using Avalonia.VisualTree;
 using Avalonia.VisualTree;
 using ChunkyImageLib;
 using ChunkyImageLib;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
@@ -40,6 +41,9 @@ public class NodeView : TemplatedControl
     public static readonly StyledProperty<bool> IsSelectedProperty = AvaloniaProperty.Register<NodeView, bool>(
     public static readonly StyledProperty<bool> IsSelectedProperty = AvaloniaProperty.Register<NodeView, bool>(
         nameof(IsSelected));
         nameof(IsSelected));
 
 
+    public static readonly StyledProperty<IBrush> CategoryBackgroundBrushProperty = AvaloniaProperty.Register<NodeView, IBrush>(
+        nameof(CategoryBackgroundBrush));
+
     public static readonly StyledProperty<ICommand> SelectNodeCommandProperty =
     public static readonly StyledProperty<ICommand> SelectNodeCommandProperty =
         AvaloniaProperty.Register<NodeView, ICommand>("SelectNodeCommand");
         AvaloniaProperty.Register<NodeView, ICommand>("SelectNodeCommand");
 
 
@@ -88,6 +92,12 @@ public class NodeView : TemplatedControl
         set => SetValue(DisplayNameProperty, value);
         set => SetValue(DisplayNameProperty, value);
     }
     }
 
 
+    public IBrush CategoryBackgroundBrush
+    {
+        get => GetValue(CategoryBackgroundBrushProperty);
+        set => SetValue(CategoryBackgroundBrushProperty, value);
+    }
+
     public ICommand SelectNodeCommand
     public ICommand SelectNodeCommand
     {
     {
         get { return (ICommand)GetValue(SelectNodeCommandProperty); }
         get { return (ICommand)GetValue(SelectNodeCommandProperty); }