Browse Source

Merge branch 'prototype-integration' of https://github.com/PixiEditor/PixiEditor into prototype-integration

Krzysztof Krysiński 2 years ago
parent
commit
9c2a44ce10
31 changed files with 278 additions and 194 deletions
  1. 6 7
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/BrightnessToolExecutor.cs
  2. 1 1
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/LassoToolExecuter.cs
  3. 4 5
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/PenToolExecutor.cs
  4. 4 4
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/SelectToolExecutor.cs
  5. 5 5
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/ShiftLayerExecutor.cs
  6. 5 5
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/TransformSelectedAreaExecutor.cs
  7. 17 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tool.cs
  8. 1 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/BoolSetting.cs
  9. 6 3
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/ColorSetting.cs
  10. 0 52
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/DropdownSetting.cs
  11. 6 4
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/EnumSetting.cs
  12. 1 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/FloatSetting.cs
  13. 5 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/Setting.cs
  14. 2 2
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/SizeSetting.cs
  15. 0 15
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/BrightnessToolToolbar.cs
  16. 0 14
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/LassoToolbar.cs
  17. 0 16
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/MagicWandToolbar.cs
  18. 0 12
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/MoveToolToolbar.cs
  19. 0 12
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/PenToolbar.cs
  20. 0 17
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/SelectToolToolbar.cs
  21. 85 0
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/SettingAttributes.cs
  22. 72 0
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/ToolbarFactory.cs
  23. 12 3
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/BrightnessToolViewModel.cs
  24. 4 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/EraserToolViewModel.cs
  25. 0 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/FloodFillToolViewModel.cs
  26. 9 5
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/LassoToolViewModel.cs
  27. 4 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/LineToolViewModel.cs
  28. 9 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/MagicWandToolViewModel.cs
  29. 4 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/MoveToolViewModel.cs
  30. 9 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/PenToolViewModel.cs
  31. 7 2
      src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/SelectToolViewModel.cs

+ 6 - 7
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/BrightnessToolExecutor.cs

@@ -19,18 +19,17 @@ internal class BrightnessToolExecutor : UpdateableChangeExecutor
     {
     {
         ViewModelMain? vm = ViewModelMain.Current;
         ViewModelMain? vm = ViewModelMain.Current;
         StructureMemberViewModel? member = document!.SelectedStructureMember;
         StructureMemberViewModel? member = document!.SelectedStructureMember;
-        BrightnessToolViewModel? brightnessTool = vm?.ToolsSubViewModel.GetTool<BrightnessToolViewModel>();
-        BrightnessToolToolbar? toolbar = brightnessTool?.Toolbar as BrightnessToolToolbar;
-        if (vm is null || brightnessTool is null || member is null || toolbar is null)
+        BrightnessToolViewModel? tool = vm?.ToolsSubViewModel.GetTool<BrightnessToolViewModel>();
+        if (vm is null || tool is null || member is null)
             return ExecutionState.Error;
             return ExecutionState.Error;
         if (member is not LayerViewModel layer || layer.ShouldDrawOnMask)
         if (member is not LayerViewModel layer || layer.ShouldDrawOnMask)
             return ExecutionState.Error;
             return ExecutionState.Error;
 
 
         guidValue = member.GuidValue;
         guidValue = member.GuidValue;
-        repeat = toolbar.BrightnessMode == BrightnessMode.Repeat;
-        toolSize = toolbar.ToolSize;
-        darken = brightnessTool.Darken;
-        correctionFactor = toolbar.CorrectionFactor;
+        repeat = tool.BrightnessMode == BrightnessMode.Repeat;
+        toolSize = tool.ToolSize;
+        darken = tool.Darken;
+        correctionFactor = tool.CorrectionFactor;
 
 
         ChangeBrightness_Action action = new(guidValue, controller!.LastPixelPosition, correctionFactor, toolSize, repeat, darken);
         ChangeBrightness_Action action = new(guidValue, controller!.LastPixelPosition, correctionFactor, toolSize, repeat, darken);
         internals!.ActionAccumulator.AddActions(action);
         internals!.ActionAccumulator.AddActions(action);

+ 1 - 1
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/LassoToolExecuter.cs

@@ -12,7 +12,7 @@ internal sealed class LassoToolExecuter : UpdateableChangeExecutor
     
     
     public override ExecutionState Start()
     public override ExecutionState Start()
     {
     {
-        mode = ((LassoToolbar)ViewModelMain.Current?.ToolsSubViewModel.GetTool<LassoToolViewModel>()?.Toolbar)?.SelectMode;
+        mode = ViewModelMain.Current?.ToolsSubViewModel.GetTool<LassoToolViewModel>()?.SelectMode;
 
 
         if (mode == null)
         if (mode == null)
             return ExecutionState.Error;
             return ExecutionState.Error;

+ 4 - 5
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/PenToolExecutor.cs

@@ -21,11 +21,10 @@ internal class PenToolExecutor : UpdateableChangeExecutor
     {
     {
         ViewModelMain? vm = ViewModelMain.Current;
         ViewModelMain? vm = ViewModelMain.Current;
         StructureMemberViewModel? member = document!.SelectedStructureMember;
         StructureMemberViewModel? member = document!.SelectedStructureMember;
-        PenToolViewModel? penTool = (PenToolViewModel?)(vm?.ToolsSubViewModel.GetTool<PenToolViewModel>());
-        PenToolbar? toolbar = penTool?.Toolbar as PenToolbar;
-        if (vm is null || penTool is null || member is null || toolbar is null)
+        PenToolViewModel? penTool = vm?.ToolsSubViewModel.GetTool<PenToolViewModel>();
+        if (vm is null || penTool is null || member is null || penTool?.Toolbar is not BasicToolbar toolbar)
             return ExecutionState.Error;
             return ExecutionState.Error;
-        drawOnMask = member is LayerViewModel layer ? layer.ShouldDrawOnMask : true;
+        drawOnMask = member is not LayerViewModel layer || layer.ShouldDrawOnMask;
         if (drawOnMask && !member.HasMaskBindable)
         if (drawOnMask && !member.HasMaskBindable)
             return ExecutionState.Error;
             return ExecutionState.Error;
         if (!drawOnMask && member is not LayerViewModel)
         if (!drawOnMask && member is not LayerViewModel)
@@ -34,7 +33,7 @@ internal class PenToolExecutor : UpdateableChangeExecutor
         guidValue = member.GuidValue;
         guidValue = member.GuidValue;
         color = vm.ColorsSubViewModel.PrimaryColor;
         color = vm.ColorsSubViewModel.PrimaryColor;
         toolSize = toolbar.ToolSize;
         toolSize = toolbar.ToolSize;
-        pixelPerfect = toolbar.PixelPerfectEnabled;
+        pixelPerfect = penTool.PixelPerfectEnabled;
 
 
         vm.ColorsSubViewModel.AddSwatch(color);
         vm.ColorsSubViewModel.AddSwatch(color);
         IAction? action = pixelPerfect switch
         IAction? action = pixelPerfect switch

+ 4 - 4
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/SelectToolExecutor.cs

@@ -16,7 +16,7 @@ namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 internal class SelectToolExecutor : UpdateableChangeExecutor
 internal class SelectToolExecutor : UpdateableChangeExecutor
 {
 {
     private SelectToolViewModel? toolViewModel;
     private SelectToolViewModel? toolViewModel;
-    private SelectToolToolbar? toolbar;
+    private Toolbar? toolbar;
     private VecI startPos;
     private VecI startPos;
     private SelectionShape selectShape;
     private SelectionShape selectShape;
     private SelectionMode selectMode;
     private SelectionMode selectMode;
@@ -24,14 +24,14 @@ internal class SelectToolExecutor : UpdateableChangeExecutor
     public override ExecutionState Start()
     public override ExecutionState Start()
     {
     {
         toolViewModel = ViewModelMain.Current?.ToolsSubViewModel.GetTool<SelectToolViewModel>();
         toolViewModel = ViewModelMain.Current?.ToolsSubViewModel.GetTool<SelectToolViewModel>();
-        toolbar = (SelectToolToolbar?)(toolViewModel?.Toolbar);
+        toolbar = toolViewModel?.Toolbar;
 
 
         if (toolViewModel is null || toolbar is null)
         if (toolViewModel is null || toolbar is null)
             return ExecutionState.Error;
             return ExecutionState.Error;
         
         
         startPos = controller!.LastPixelPosition;
         startPos = controller!.LastPixelPosition;
-        selectShape = toolbar.SelectShape;
-        selectMode = toolbar.SelectMode;
+        selectShape = toolViewModel.SelectShape;
+        selectMode = toolViewModel.SelectMode;
 
 
         IAction action = CreateUpdateAction(selectShape, new RectI(startPos, new(0)), selectMode);
         IAction action = CreateUpdateAction(selectShape, new RectI(startPos, new(0)), selectMode);
         internals!.ActionAccumulator.AddActions(action);
         internals!.ActionAccumulator.AddActions(action);

+ 5 - 5
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/ShiftLayerExecutor.cs

@@ -11,20 +11,20 @@ internal class ShiftLayerExecutor : UpdateableChangeExecutor
 {
 {
     private Guid guidValue;
     private Guid guidValue;
     private VecI startPos;
     private VecI startPos;
-    private MoveToolToolbar? toolbar;
+    private MoveToolViewModel? tool;
 
 
     public override ExecutionState Start()
     public override ExecutionState Start()
     {
     {
         ViewModelMain? vm = ViewModelMain.Current;
         ViewModelMain? vm = ViewModelMain.Current;
         StructureMemberViewModel? member = document!.SelectedStructureMember;
         StructureMemberViewModel? member = document!.SelectedStructureMember;
-        toolbar = (MoveToolToolbar?)(ViewModelMain.Current?.ToolsSubViewModel.GetTool<MoveToolViewModel>()?.Toolbar);
-        if (vm is null || member is not LayerViewModel layer || layer.ShouldDrawOnMask || toolbar is null)
+        tool = ViewModelMain.Current?.ToolsSubViewModel.GetTool<MoveToolViewModel>();
+        if (vm is null || member is not LayerViewModel layer || layer.ShouldDrawOnMask || tool is null)
             return ExecutionState.Error;
             return ExecutionState.Error;
 
 
         guidValue = member.GuidValue;
         guidValue = member.GuidValue;
         startPos = controller!.LastPixelPosition;
         startPos = controller!.LastPixelPosition;
 
 
-        ShiftLayer_Action action = new(guidValue, VecI.Zero, toolbar.KeepOriginalImage);
+        ShiftLayer_Action action = new(guidValue, VecI.Zero, tool.KeepOriginalImage);
         internals!.ActionAccumulator.AddActions(action);
         internals!.ActionAccumulator.AddActions(action);
 
 
         return ExecutionState.Success;
         return ExecutionState.Success;
@@ -32,7 +32,7 @@ internal class ShiftLayerExecutor : UpdateableChangeExecutor
 
 
     public override void OnPixelPositionChange(VecI pos)
     public override void OnPixelPositionChange(VecI pos)
     {
     {
-        ShiftLayer_Action action = new(guidValue, pos - startPos, toolbar!.KeepOriginalImage);
+        ShiftLayer_Action action = new(guidValue, pos - startPos, tool!.KeepOriginalImage);
         internals!.ActionAccumulator.AddActions(action);
         internals!.ActionAccumulator.AddActions(action);
     }
     }
 
 

+ 5 - 5
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/TransformSelectedAreaExecutor.cs

@@ -9,7 +9,7 @@ namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 internal class TransformSelectedAreaExecutor : UpdateableChangeExecutor
 internal class TransformSelectedAreaExecutor : UpdateableChangeExecutor
 {
 {
     private Guid[]? membersToTransform;
     private Guid[]? membersToTransform;
-    private MoveToolToolbar? toolbar;
+    private MoveToolViewModel? tool;
 
 
     public override ExecutorType Type { get; }
     public override ExecutorType Type { get; }
 
 
@@ -20,8 +20,8 @@ internal class TransformSelectedAreaExecutor : UpdateableChangeExecutor
 
 
     public override ExecutionState Start()
     public override ExecutionState Start()
     {
     {
-        toolbar = (MoveToolToolbar?)(ViewModelMain.Current?.ToolsSubViewModel.GetTool<MoveToolViewModel>()?.Toolbar);
-        if (toolbar is null || document!.SelectedStructureMember is null || document!.SelectionPathBindable.IsEmpty)
+        tool = ViewModelMain.Current?.ToolsSubViewModel.GetTool<MoveToolViewModel>();
+        if (tool is null || document!.SelectedStructureMember is null || document!.SelectionPathBindable.IsEmpty)
             return ExecutionState.Error;
             return ExecutionState.Error;
 
 
         var members = document.SoftSelectedStructureMembers
         var members = document.SoftSelectedStructureMembers
@@ -35,14 +35,14 @@ internal class TransformSelectedAreaExecutor : UpdateableChangeExecutor
         document.TransformViewModel.ShowTransform(DocumentTransformMode.Freeform, true, corners);
         document.TransformViewModel.ShowTransform(DocumentTransformMode.Freeform, true, corners);
         membersToTransform = members.Select(static a => a.GuidValue).ToArray();
         membersToTransform = members.Select(static a => a.GuidValue).ToArray();
         internals!.ActionAccumulator.AddActions(
         internals!.ActionAccumulator.AddActions(
-            new TransformSelectedArea_Action(membersToTransform, corners, toolbar.KeepOriginalImage, false));
+            new TransformSelectedArea_Action(membersToTransform, corners, tool.KeepOriginalImage, false));
         return ExecutionState.Success;
         return ExecutionState.Success;
     }
     }
 
 
     public override void OnTransformMoved(ShapeCorners corners)
     public override void OnTransformMoved(ShapeCorners corners)
     {
     {
         internals!.ActionAccumulator.AddActions(
         internals!.ActionAccumulator.AddActions(
-            new TransformSelectedArea_Action(membersToTransform!, corners, toolbar!.KeepOriginalImage, false));
+            new TransformSelectedArea_Action(membersToTransform!, corners, tool!.KeepOriginalImage, false));
     }
     }
 
 
     public override void OnTransformApplied()
     public override void OnTransformApplied()

+ 17 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/Tool.cs

@@ -1,7 +1,10 @@
-using System.Windows.Input;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Windows.Input;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
+using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 
 
@@ -53,4 +56,17 @@ internal abstract class ToolViewModel : NotifyableObject
     public virtual void OnLeftMouseButtonDown(VecD pos) { }
     public virtual void OnLeftMouseButtonDown(VecD pos) { }
     public virtual void OnSelected() { }
     public virtual void OnSelected() { }
     public virtual void OnDeselected() { }
     public virtual void OnDeselected() { }
+
+    protected T GetValue<T>([CallerMemberName] string name = null)
+    {
+        var setting = Toolbar.GetSetting(name);
+
+        if (setting.GetSettingType().IsAssignableTo(typeof(Enum)))
+        {
+            var property = setting.GetType().GetProperty("Value",  BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
+            return (T)property!.GetValue(setting);
+        }
+
+        return (T)setting.Value;
+    }
 }
 }

+ 1 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/BoolSetting.cs

@@ -5,7 +5,7 @@ using System.Windows.Data;
 
 
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 
 
-internal class BoolSetting : Setting<bool>
+internal sealed class BoolSetting : Setting<bool>
 {
 {
     public BoolSetting(string name, string label = "")
     public BoolSetting(string name, string label = "")
         : this(name, false, label)
         : this(name, false, label)

+ 6 - 3
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/ColorSetting.cs

@@ -8,13 +8,16 @@ using PixiEditor.Views.UserControls;
 
 
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 
 
-internal class ColorSetting : Setting<Color>
+internal sealed class ColorSetting : Setting<Color>
 {
 {
-    public ColorSetting(string name, string label = "")
+    public ColorSetting(string name, string label = "") : this(name, Colors.White, label)
+    { }
+    
+    public ColorSetting(string name, Color defaultValue, string label = "")
         : base(name)
         : base(name)
     {
     {
         Label = label;
         Label = label;
-        Value = Color.FromArgb(255, 255, 255, 255);
+        Value = defaultValue;
     }
     }
 
 
     private ToolSettingColorPicker GenerateColorPicker()
     private ToolSettingColorPicker GenerateColorPicker()

+ 0 - 52
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/DropdownSetting.cs

@@ -1,52 +0,0 @@
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Data;
-
-namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
-
-internal class DropdownSetting : Setting<object>
-{
-    public DropdownSetting(string name, string[] values, string label)
-        : base(name)
-    {
-        Values = values;
-        Value = ((ComboBox)SettingControl).Items[0];
-        Label = label;
-    }
-
-    public string[] Values { get; set; }
-
-    private ComboBox GenerateDropdown()
-    {
-        var combobox = new ComboBox
-        {
-            VerticalAlignment = VerticalAlignment.Center
-        };
-        GenerateItems(combobox);
-
-        var binding = new Binding("Value")
-        {
-            Mode = BindingMode.TwoWay
-        };
-        combobox.SetBinding(Selector.SelectedValueProperty, binding);
-        return combobox;
-    }
-
-    private void GenerateItems(ComboBox comboBox)
-    {
-        for (var i = 0; i < Values.Length; i++)
-        {
-            var item = new ComboBoxItem
-            {
-                Content = Values[i]
-            };
-            comboBox.Items.Add(item);
-        }
-    }
-
-    public override Control GenerateControl()
-    {
-        return GenerateDropdown();
-    }
-}

+ 6 - 4
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/EnumSetting.cs

@@ -6,10 +6,10 @@ using PixiEditor.Helpers.Extensions;
 
 
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 
 
-internal class EnumSetting<TEnum> : Setting<TEnum, ComboBox>
+internal sealed class EnumSetting<TEnum> : Setting<TEnum, ComboBox>
     where TEnum : struct, Enum
     where TEnum : struct, Enum
 {
 {
-    private int selectedIndex = 0;
+    private int selectedIndex;
 
 
     /// <summary>
     /// <summary>
     /// Gets or sets the selected Index of the <see cref="ComboBox"/>.
     /// Gets or sets the selected Index of the <see cref="ComboBox"/>.
@@ -29,7 +29,7 @@ internal class EnumSetting<TEnum> : Setting<TEnum, ComboBox>
     /// <summary>
     /// <summary>
     /// Gets or sets the selected value of the <see cref="ComboBox"/>.
     /// Gets or sets the selected value of the <see cref="ComboBox"/>.
     /// </summary>
     /// </summary>
-    public new TEnum Value
+    public override TEnum Value
     {
     {
         get => (TEnum)(SettingControl.SelectedItem as ComboBoxItem).Tag;
         get => (TEnum)(SettingControl.SelectedItem as ComboBoxItem).Tag;
         set
         set
@@ -43,6 +43,8 @@ internal class EnumSetting<TEnum> : Setting<TEnum, ComboBox>
                     SelectedIndex = i;
                     SelectedIndex = i;
                 }
                 }
             }
             }
+
+            base.Value = value;
         }
         }
     }
     }
 
 
@@ -60,7 +62,7 @@ internal class EnumSetting<TEnum> : Setting<TEnum, ComboBox>
     public EnumSetting(string name, string label, TEnum defaultValue)
     public EnumSetting(string name, string label, TEnum defaultValue)
         : this(name, label)
         : this(name, label)
     {
     {
-        Value = defaultValue;
+        base.Value = defaultValue;
     }
     }
 
 
     private static ComboBox GenerateDropdown()
     private static ComboBox GenerateDropdown()

+ 1 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/FloatSetting.cs

@@ -4,7 +4,7 @@ using PixiEditor.Views.UserControls;
 
 
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 
 
-internal class FloatSetting : Setting<float>
+internal sealed class FloatSetting : Setting<float>
 {
 {
     public FloatSetting(
     public FloatSetting(
         string name,
         string name,

+ 5 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/Setting.cs

@@ -28,7 +28,7 @@ internal abstract class Setting<T> : Setting
 
 
     public event EventHandler<SettingValueChangedEventArgs<T>> ValueChanged;
     public event EventHandler<SettingValueChangedEventArgs<T>> ValueChanged;
 
 
-    public new T Value
+    public new virtual T Value
     {
     {
         get => (T)base.Value;
         get => (T)base.Value;
         set
         set
@@ -44,6 +44,8 @@ internal abstract class Setting<T> : Setting
             RaisePropertyChanged(nameof(Value));
             RaisePropertyChanged(nameof(Value));
         }
         }
     }
     }
+
+    public override Type GetSettingType() => typeof(T);
 }
 }
 
 
 internal abstract class Setting : NotifyableObject
 internal abstract class Setting : NotifyableObject
@@ -64,4 +66,6 @@ internal abstract class Setting : NotifyableObject
     public Control SettingControl { get; set; }
     public Control SettingControl { get; set; }
 
 
     public abstract Control GenerateControl();
     public abstract Control GenerateControl();
+
+    public abstract Type GetSettingType();
 }
 }

+ 2 - 2
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/SizeSetting.cs

@@ -5,13 +5,13 @@ using PixiEditor.Views.UserControls;
 
 
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 
 
-internal class SizeSetting : Setting<int>
+internal sealed class SizeSetting : Setting<int>
 {
 {
     public SizeSetting(string name, string label = null)
     public SizeSetting(string name, string label = null)
         : base(name)
         : base(name)
     {
     {
-        Value = 1;
         Label = label;
         Label = label;
+        Value = 1;
     }
     }
 
 
     private SizeInput GenerateTextBox()
     private SizeInput GenerateTextBox()

+ 0 - 15
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/BrightnessToolToolbar.cs

@@ -1,15 +0,0 @@
-using PixiEditor.Models.Enums;
-using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
-
-namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
-
-internal class BrightnessToolToolbar : BasicToolbar
-{
-    public float CorrectionFactor => GetSetting<FloatSetting>(nameof(CorrectionFactor)).Value;
-    public BrightnessMode BrightnessMode => GetSetting<EnumSetting<BrightnessMode>>(nameof(BrightnessMode)).Value;
-    public BrightnessToolToolbar(float initialValue)
-    {
-        Settings.Add(new FloatSetting(nameof(CorrectionFactor), initialValue, "Strength:", 0f, 100f));
-        Settings.Add(new EnumSetting<BrightnessMode>(nameof(BrightnessMode), "Mode"));
-    }
-}

+ 0 - 14
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/LassoToolbar.cs

@@ -1,14 +0,0 @@
-using PixiEditor.ChangeableDocument.Enums;
-using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
-
-namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
-
-internal class LassoToolbar : Toolbar
-{
-    public SelectionMode SelectMode => GetSetting<EnumSetting<SelectionMode>>(nameof(SelectMode)).Value;
-    
-    public LassoToolbar()
-    {
-        Settings.Add(new EnumSetting<SelectionMode>(nameof(SelectMode), "Selection type"));
-    }
-}

+ 0 - 16
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/MagicWandToolbar.cs

@@ -1,16 +0,0 @@
-using System.Windows.Controls;
-using PixiEditor.Models.Enums;
-using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
-
-namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
-
-internal class MagicWandToolbar : Toolbar
-{
-    public SelectionMode SelectMode => GetSetting<EnumSetting<SelectionMode>>(nameof(SelectMode)).Value;
-    public DocumentScope DocumentScope => GetSetting<EnumSetting<DocumentScope>>(nameof(DocumentScope)).Value;
-    public MagicWandToolbar()
-    {
-        Settings.Add(new EnumSetting<SelectionMode>(nameof(SelectMode), "Selection type"));
-        Settings.Add(new EnumSetting<DocumentScope>(nameof(DocumentScope), "Scope"));
-    }
-}

+ 0 - 12
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/MoveToolToolbar.cs

@@ -1,12 +0,0 @@
-using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
-
-namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
-internal class MoveToolToolbar : Toolbar
-{
-    public bool KeepOriginalImage => GetSetting<BoolSetting>(nameof(KeepOriginalImage)).Value;
-
-    public MoveToolToolbar()
-    {
-        Settings.Add(new BoolSetting(nameof(KeepOriginalImage), "Kеep original image"));
-    }
-}

+ 0 - 12
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/PenToolbar.cs

@@ -1,12 +0,0 @@
-using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
-
-namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
-
-internal class PenToolbar : BasicToolbar
-{
-    public bool PixelPerfectEnabled => GetSetting<BoolSetting>(nameof(PixelPerfectEnabled)).Value;
-    public PenToolbar()
-    {
-        Settings.Add(new BoolSetting(nameof(PixelPerfectEnabled), "Pixel perfect"));
-    }
-}

+ 0 - 17
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/SelectToolToolbar.cs

@@ -1,17 +0,0 @@
-using PixiEditor.ChangeableDocument.Enums;
-using PixiEditor.Models.Enums;
-using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
-
-namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
-
-internal class SelectToolToolbar : Toolbar
-{
-    public SelectionMode SelectMode => GetSetting<EnumSetting<SelectionMode>>(nameof(SelectMode)).Value;
-    public SelectionShape SelectShape => GetSetting<EnumSetting<SelectionShape>>(nameof(SelectShape)).Value;
-
-    public SelectToolToolbar()
-    {
-        Settings.Add(new EnumSetting<SelectionMode>(nameof(SelectMode), "Selection type"));
-        Settings.Add(new EnumSetting<SelectionShape>(nameof(SelectShape), "Selection shape"));
-    }
-}

+ 85 - 0
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/SettingAttributes.cs

@@ -0,0 +1,85 @@
+using System.Reflection.Emit;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
+
+namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
+
+public static class Settings
+{
+    /// <summary>
+    /// A toolbar setting of type <see cref="bool"/>
+    /// </summary>
+    public class BoolAttribute : SettingsAttribute
+    {
+        public BoolAttribute(string label) : base(label) { }
+
+        public BoolAttribute(string label, object defaultValue) : base(label, defaultValue) { }
+    }
+
+    /// <summary>
+    /// A toolbar setting of any enum
+    /// </summary>
+    public class EnumAttribute : SettingsAttribute
+    {
+        public EnumAttribute(string label) : base(label) { }
+
+        public EnumAttribute(string label, object defaultValue) : base(label, defaultValue) { }
+    }
+
+    /// <summary>
+    /// A toolbar setting of type <see cref="Color"/>
+    /// </summary>
+    public class ColorAttribute : SettingsAttribute
+    {
+        public ColorAttribute(string label) : base(label) { }
+
+        public ColorAttribute(string label, byte r, byte g, byte b) : base(label, new Color(r, g, b)) { }
+        
+        public ColorAttribute(string label, byte r, byte g, byte b, byte a) : base(label, new Color(r, g, b, a)) { }
+    }
+
+    /// <summary>
+    /// A toolbar setting of type <see cref="float"/>
+    /// </summary>
+    public class FloatAttribute : SettingsAttribute
+    {
+        public FloatAttribute(string label) : base(label) { }
+
+        public FloatAttribute(string label, float defaultValue) : base(label, defaultValue) { }
+    }
+
+    /// <summary>
+    /// A toolbar setting of type <see cref="int"/>
+    /// </summary>
+    public class SizeAttribute : SettingsAttribute
+    {
+        public SizeAttribute(string label) : base(label) { }
+    }
+
+    /// <summary>
+    /// Marks a setting to be inherited from the toolbar type
+    /// </summary>
+    public class InheritedAttribute : SettingsAttribute { }
+
+    [AttributeUsage(AttributeTargets.Property)]
+    public abstract class SettingsAttribute : Attribute
+    {
+        public string Name { get; set; }
+
+        public SettingsAttribute() { }
+        
+        public SettingsAttribute(string label)
+        {
+            Label = label;
+        }
+
+        public SettingsAttribute(string label, object defaultValue)
+        {
+            Label = label;
+            DefaultValue = defaultValue;
+        }
+        
+        public readonly string Label;
+
+        public readonly object DefaultValue;
+    }
+}

+ 72 - 0
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Toolbars/ToolbarFactory.cs

@@ -0,0 +1,72 @@
+using System.Reflection;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
+using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
+
+namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
+
+internal static class ToolbarFactory
+{
+    public static Toolbar Create<T>() where T : ToolViewModel => Create<T, EmptyToolbar>();
+
+    public static TToolbar Create<T, TToolbar>() where T : ToolViewModel where TToolbar : Toolbar, new()
+    {
+        var tool = typeof(T);
+        var toolbar = new TToolbar();
+
+        foreach (var property in tool.GetProperties())
+        {
+            var attribute = property.GetCustomAttribute<Settings.SettingsAttribute>();
+
+            if (attribute == null)
+                continue;
+            
+            var name = attribute.Name ?? property.Name;
+
+            if (attribute is Settings.InheritedAttribute)
+            {
+                var inherited = toolbar.GetSetting(name);
+                
+                if (inherited == null)
+                {
+                    throw new NullReferenceException($"There's no inherited setting '{name}' on inherited toolbar of type '{typeof(TToolbar).FullName}' (Tool: {typeof(T).FullName})");
+                }
+
+                if (inherited.GetSettingType() != property.PropertyType)
+                {
+                    throw new InvalidCastException($"Inherited setting '{name}' does not match property type '{property.PropertyType}' (Tool: {typeof(T).FullName})");
+                }
+
+                continue;
+            }
+            
+            var label = attribute.Label ?? name;
+
+            var setting = attribute switch
+            {
+                Settings.BoolAttribute => new BoolSetting(name, (bool)(attribute.DefaultValue ?? false), label),
+                Settings.ColorAttribute => new ColorSetting(name, ((Color)(attribute.DefaultValue ?? Colors.White)).ToColor(), label),
+                Settings.EnumAttribute => GetEnumSetting(property.PropertyType, name, attribute),
+                Settings.FloatAttribute => new FloatSetting(name, (float)(attribute.DefaultValue ?? 0f), attribute.Label),
+                Settings.SizeAttribute => new SizeSetting(name, label),
+                _ => throw new NotImplementedException($"SettingsAttribute of type '{attribute.GetType().FullName}' has not been implemented")
+            };
+            
+            if (setting.GetSettingType() != property.PropertyType)
+            {
+                throw new InvalidCastException($"Setting '{name}' does not match property type '{property.PropertyType}' (Tool: {typeof(T).FullName})");
+            }
+
+            toolbar.Settings.Add(setting);
+        }
+
+        return toolbar;
+    }
+
+    private static Setting GetEnumSetting(Type enumType, string name, Settings.SettingsAttribute attribute)
+    {
+        return (Setting)typeof(EnumSetting<>)
+            .MakeGenericType(enumType)
+            .GetConstructor(new[] { typeof(string), typeof(string), enumType })!
+            .Invoke(new[] { name, attribute.Label ?? name, attribute.DefaultValue });
+    }
+}

+ 12 - 3
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/BrightnessToolViewModel.cs

@@ -2,6 +2,8 @@
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Commands.Attributes.Commands;
+using PixiEditor.Models.Enums;
+using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 
 
@@ -10,20 +12,27 @@ namespace PixiEditor.ViewModels.SubViewModels.Tools.Tools;
 [Command.Tool(Key = Key.U)]
 [Command.Tool(Key = Key.U)]
 internal class BrightnessToolViewModel : ToolViewModel
 internal class BrightnessToolViewModel : ToolViewModel
 {
 {
-    private const float CorrectionFactor = 5f;
-
     private readonly string defaultActionDisplay = "Draw on pixels to make them brighter. Hold Ctrl to darken.";
     private readonly string defaultActionDisplay = "Draw on pixels to make them brighter. Hold Ctrl to darken.";
 
 
     public BrightnessToolViewModel()
     public BrightnessToolViewModel()
     {
     {
         ActionDisplay = defaultActionDisplay;
         ActionDisplay = defaultActionDisplay;
-        Toolbar = new BrightnessToolToolbar(CorrectionFactor);
+        Toolbar = ToolbarFactory.Create<BrightnessToolViewModel, BasicToolbar>();
     }
     }
 
 
     public override string Tooltip => $"Makes pixels brighter or darker ({Shortcut}). Hold Ctrl to make pixels darker.";
     public override string Tooltip => $"Makes pixels brighter or darker ({Shortcut}). Hold Ctrl to make pixels darker.";
 
 
     public override BrushShape BrushShape => BrushShape.Circle;
     public override BrushShape BrushShape => BrushShape.Circle;
 
 
+    [Settings.Inherited]
+    public int ToolSize => GetValue<int>();
+    
+    [Settings.Float("Strength", 5)]
+    public float CorrectionFactor => GetValue<float>();
+
+    [Settings.Enum("Mode")]
+    public BrightnessMode BrightnessMode => GetValue<BrightnessMode>();
+    
     public bool Darken { get; private set; } = false;
     public bool Darken { get; private set; } = false;
 
 
     public override void UpdateActionDisplay(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     public override void UpdateActionDisplay(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)

+ 4 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/EraserToolViewModel.cs

@@ -13,9 +13,12 @@ internal class EraserToolViewModel : ToolViewModel
     public EraserToolViewModel()
     public EraserToolViewModel()
     {
     {
         ActionDisplay = "Draw to remove color from a pixel.";
         ActionDisplay = "Draw to remove color from a pixel.";
-        Toolbar = new BasicToolbar();
+        Toolbar = ToolbarFactory.Create<EraserToolViewModel, BasicToolbar>();
     }
     }
 
 
+    [Settings.Inherited]
+    public int ToolSize => GetValue<int>();
+
     public override BrushShape BrushShape => BrushShape.Circle;
     public override BrushShape BrushShape => BrushShape.Circle;
 
 
     public override string Tooltip => $"Erasers color from pixel. ({Shortcut})";
     public override string Tooltip => $"Erasers color from pixel. ({Shortcut})";

+ 0 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/FloodFillToolViewModel.cs

@@ -10,7 +10,6 @@ namespace PixiEditor.ViewModels.SubViewModels.Tools.Tools;
 internal class FloodFillToolViewModel : ToolViewModel
 internal class FloodFillToolViewModel : ToolViewModel
 {
 {
     private readonly string defaultActionDisplay = "Press on an area to fill it. Hold down Ctrl to consider all layers.";
     private readonly string defaultActionDisplay = "Press on an area to fill it. Hold down Ctrl to consider all layers.";
-    private SKPaint fillPaint = new SKPaint() { BlendMode = SKBlendMode.Src };
 
 
     public override BrushShape BrushShape => BrushShape.Pixel;
     public override BrushShape BrushShape => BrushShape.Pixel;
 
 

+ 9 - 5
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/LassoToolViewModel.cs

@@ -1,4 +1,5 @@
 using System.Windows.Input;
 using System.Windows.Input;
+using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
@@ -9,16 +10,19 @@ namespace PixiEditor.ViewModels.SubViewModels.Tools.Tools;
 [Command.ToolAttribute(Key = Key.L)]
 [Command.ToolAttribute(Key = Key.L)]
 internal class LassoToolViewModel : ToolViewModel
 internal class LassoToolViewModel : ToolViewModel
 {
 {
-    public override string Tooltip => $"Lasso. ({Shortcut})";
-    
-    public override BrushShape BrushShape => BrushShape.Pixel;
-
     public LassoToolViewModel()
     public LassoToolViewModel()
     {
     {
-        Toolbar = new LassoToolbar();
+        Toolbar = ToolbarFactory.Create<LassoToolViewModel>();
         ActionDisplay = "Click and move to select pixels inside of lasso.";
         ActionDisplay = "Click and move to select pixels inside of lasso.";
     }
     }
 
 
+    public override string Tooltip => $"Lasso. ({Shortcut})";
+    
+    public override BrushShape BrushShape => BrushShape.Pixel;
+
+    [Settings.Enum("Mode")]
+    public SelectionMode SelectMode => GetValue<SelectionMode>();
+    
     public override void OnLeftMouseButtonDown(VecD pos)
     public override void OnLeftMouseButtonDown(VecD pos)
     {
     {
         ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseLassoTool();
         ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseLassoTool();

+ 4 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/LineToolViewModel.cs

@@ -14,11 +14,14 @@ internal class LineToolViewModel : ShapeTool
     public LineToolViewModel()
     public LineToolViewModel()
     {
     {
         ActionDisplay = defaultActionDisplay;
         ActionDisplay = defaultActionDisplay;
-        Toolbar = new BasicToolbar();
+        Toolbar = ToolbarFactory.Create<LineToolViewModel, BasicToolbar>();
     }
     }
 
 
     public override string Tooltip => $"Draws line on canvas ({Shortcut}). Hold Shift to draw even line.";
     public override string Tooltip => $"Draws line on canvas ({Shortcut}). Hold Shift to draw even line.";
 
 
+    [Settings.Inherited]
+    public int ToolSize => GetValue<int>();
+
     public override void UpdateActionDisplay(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     public override void UpdateActionDisplay(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
     {
         if (shiftIsDown)
         if (shiftIsDown)

+ 9 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/MagicWandToolViewModel.cs

@@ -1,5 +1,7 @@
 using System.Windows.Input;
 using System.Windows.Input;
+using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Commands.Attributes.Commands;
+using PixiEditor.Models.Enums;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 
 
@@ -12,9 +14,15 @@ internal class MagicWandToolViewModel : ToolViewModel
 
 
     public override BrushShape BrushShape => BrushShape.Pixel;
     public override BrushShape BrushShape => BrushShape.Pixel;
 
 
+    [Settings.Enum("Mode")]
+    public SelectionMode SelectMode => GetValue<SelectionMode>();
+
+    [Settings.Enum("Scope")]
+    public DocumentScope DocumentScope => GetValue<DocumentScope>();
+    
     public MagicWandToolViewModel()
     public MagicWandToolViewModel()
     {
     {
-        Toolbar = new MagicWandToolbar();
+        Toolbar = ToolbarFactory.Create<MagicWandToolViewModel>();
         ActionDisplay = "Click to flood the selection.";
         ActionDisplay = "Click to flood the selection.";
     }
     }
 }
 }

+ 4 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/MoveToolViewModel.cs

@@ -15,12 +15,15 @@ internal class MoveToolViewModel : ToolViewModel
     public MoveToolViewModel()
     public MoveToolViewModel()
     {
     {
         ActionDisplay = defaultActionDisplay;
         ActionDisplay = defaultActionDisplay;
-        Toolbar = new MoveToolToolbar();
+        Toolbar = ToolbarFactory.Create<MoveToolViewModel>();
         Cursor = Cursors.Arrow;
         Cursor = Cursors.Arrow;
     }
     }
 
 
     public override string Tooltip => $"Moves selected pixels ({Shortcut}). Hold Ctrl to move all layers.";
     public override string Tooltip => $"Moves selected pixels ({Shortcut}). Hold Ctrl to move all layers.";
 
 
+    [Settings.Bool("Keep original image")]
+    public bool KeepOriginalImage => GetValue<bool>();
+    
     public override BrushShape BrushShape => BrushShape.Hidden;
     public override BrushShape BrushShape => BrushShape.Hidden;
     public override bool HideHighlight => true;
     public override bool HideHighlight => true;
 
 

+ 9 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/PenToolViewModel.cs

@@ -1,7 +1,9 @@
 using System.Windows.Input;
 using System.Windows.Input;
+using System.Windows.Media;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Commands.Attributes.Commands;
+using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Settings;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 
 
@@ -15,11 +17,17 @@ namespace PixiEditor.ViewModels.SubViewModels.Tools.Tools
         {
         {
             Cursor = Cursors.Pen;
             Cursor = Cursors.Pen;
             ActionDisplay = "Click and move to draw.";
             ActionDisplay = "Click and move to draw.";
-            Toolbar = new PenToolbar();
+            Toolbar = ToolbarFactory.Create<PenToolViewModel, BasicToolbar>();
         }
         }
 
 
         public override string Tooltip => $"Pen. ({Shortcut})";
         public override string Tooltip => $"Pen. ({Shortcut})";
 
 
+        [Settings.Inherited]
+        public int ToolSize => GetValue<int>();
+
+        [Settings.Bool("Pixel perfect")]
+        public bool PixelPerfectEnabled => GetValue<bool>();
+
         public override void OnLeftMouseButtonDown(VecD pos)
         public override void OnLeftMouseButtonDown(VecD pos)
         {
         {
             ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UsePenTool();
             ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UsePenTool();

+ 7 - 2
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/SelectToolViewModel.cs

@@ -3,6 +3,7 @@ using ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Commands.Attributes.Commands;
+using PixiEditor.Models.Enums;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 using PixiEditor.Views.UserControls.BrushShapeOverlay;
 
 
@@ -14,12 +15,16 @@ internal class SelectToolViewModel : ToolViewModel
     public SelectToolViewModel()
     public SelectToolViewModel()
     {
     {
         ActionDisplay = "Click and move to select an area.";
         ActionDisplay = "Click and move to select an area.";
-        Toolbar = new SelectToolToolbar();
+        Toolbar = ToolbarFactory.Create<SelectToolViewModel>();
         Cursor = Cursors.Cross;
         Cursor = Cursors.Cross;
     }
     }
 
 
-    public SelectionMode SelectionType { get; set; } = SelectionMode.Add;
+    [Settings.Enum("Mode")]
+    public SelectionMode SelectMode => GetValue<SelectionMode>();
 
 
+    [Settings.Enum("Shape")]
+    public SelectionShape SelectShape => GetValue<SelectionShape>();
+    
     public override BrushShape BrushShape => BrushShape.Pixel;
     public override BrushShape BrushShape => BrushShape.Pixel;
 
 
     public override string Tooltip => $"Selects area. ({Shortcut})";
     public override string Tooltip => $"Selects area. ({Shortcut})";