2
0
flabbet 6 өдөр өмнө
parent
commit
16b1f5f056

+ 4 - 4
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Brushes/BrushOutputNode.cs

@@ -251,7 +251,7 @@ public class BrushOutputNode : Node
             previewEngine.ExecuteBrush(previewChunkyImage,
             previewEngine.ExecuteBrush(previewChunkyImage,
                 new BrushData(context.Graph, Id) { StrokeWidth = size, AntiAliasing = true },
                 new BrushData(context.Graph, Id) { StrokeWidth = size, AntiAliasing = true },
                 (VecI)pos, context.FrameTime, context.ProcessingColorSpace, context.DesiredSamplingOptions,
                 (VecI)pos, context.FrameTime, context.ProcessingColorSpace, context.DesiredSamplingOptions,
-                new PointerInfo(pos, 1, 0, VecD.Zero, new VecD(0, 1)),
+                new PointerInfo(pos, 1, 0, VecD.Zero, new VecD(0, 1), true, false),
                 new KeyboardInfo(),
                 new KeyboardInfo(),
                 new EditorData(Colors.White, Colors.Black));
                 new EditorData(Colors.White, Colors.Black));
         }
         }
@@ -284,7 +284,7 @@ public class BrushOutputNode : Node
             pos = vec4D.XY;
             pos = vec4D.XY;
             pos = new VecD(pos.X, pos.Y + maxSize / 2f) + shift;
             pos = new VecD(pos.X, pos.Y + maxSize / 2f) + shift;
 
 
-            points.Add(new RecordedPoint((VecI)pos, new PointerInfo(pos, pressure, 0, VecD.Zero, vec4D.ZW),
+            points.Add(new RecordedPoint((VecI)pos, new PointerInfo(pos, pressure, 0, VecD.Zero, vec4D.ZW, true, false),
                 new KeyboardInfo(), new EditorData(Colors.White, Colors.Black)));
                 new KeyboardInfo(), new EditorData(Colors.White, Colors.Black)));
 
 
             previewEngine.ExecuteBrush(target,
             previewEngine.ExecuteBrush(target,
@@ -316,7 +316,7 @@ public class BrushOutputNode : Node
             var vec4D = previewVectorPath.GetPositionAndTangentAtDistance(offset, false);
             var vec4D = previewVectorPath.GetPositionAndTangentAtDistance(offset, false);
             pos = vec4D.XY;
             pos = vec4D.XY;
             pos = new VecD(pos.X, pos.Y + maxSize / 2f) + shift;
             pos = new VecD(pos.X, pos.Y + maxSize / 2f) + shift;
-            points.Add(new RecordedPoint((VecI)pos, new PointerInfo(pos, pressure, 0, VecD.Zero, vec4D.ZW),
+            points.Add(new RecordedPoint((VecI)pos, new PointerInfo(pos, pressure, 0, VecD.Zero, vec4D.ZW, true, false),
                 new KeyboardInfo(), new EditorData(Colors.White, Colors.Black)));
                 new KeyboardInfo(), new EditorData(Colors.White, Colors.Black)));
 
 
             previewEngine.ExecuteBrush(target,
             previewEngine.ExecuteBrush(target,
@@ -333,7 +333,7 @@ public class BrushOutputNode : Node
         previewEngine.ExecuteBrush(img,
         previewEngine.ExecuteBrush(img,
             new BrushData(context.Graph, Id) { StrokeWidth = size, AntiAliasing = true },
             new BrushData(context.Graph, Id) { StrokeWidth = size, AntiAliasing = true },
             pos, context.FrameTime, context.ProcessingColorSpace, context.DesiredSamplingOptions,
             pos, context.FrameTime, context.ProcessingColorSpace, context.DesiredSamplingOptions,
-            new PointerInfo(pos, 1, 0, VecD.Zero, new VecD(0, 1)),
+            new PointerInfo(pos, 1, 0, VecD.Zero, new VecD(0, 1), true, false),
             new KeyboardInfo(),
             new KeyboardInfo(),
             new EditorData(Colors.White, Colors.Black));
             new EditorData(Colors.White, Colors.Black));
     }
     }

+ 6 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/PointerInfoNode.cs

@@ -7,6 +7,8 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 [NodeInfo("PointerInfo")]
 [NodeInfo("PointerInfo")]
 public class PointerInfoNode : Node
 public class PointerInfoNode : Node
 {
 {
+    public OutputProperty<bool> IsLeftButtonPressed { get; }
+    public OutputProperty<bool> IsRightButtonPressed { get; }
     public OutputProperty<VecD> PositionOnCanvas { get; }
     public OutputProperty<VecD> PositionOnCanvas { get; }
     public OutputProperty<double> Pressure { get; }
     public OutputProperty<double> Pressure { get; }
     public OutputProperty<double> Twist { get; }
     public OutputProperty<double> Twist { get; }
@@ -17,6 +19,8 @@ public class PointerInfoNode : Node
 
 
     public PointerInfoNode()
     public PointerInfoNode()
     {
     {
+        IsLeftButtonPressed = CreateOutput<bool>("IsLeftButtonPressed", "IS_LEFT_BUTTON_PRESSED", false);
+        IsRightButtonPressed = CreateOutput<bool>("IsRightButtonPressed", "IS_RIGHT_BUTTON_PRESSED", false);
         PositionOnCanvas = CreateOutput<VecD>("PositionOnCanvas", "POSITION_ON_CANVAS", new VecD(0, 0));
         PositionOnCanvas = CreateOutput<VecD>("PositionOnCanvas", "POSITION_ON_CANVAS", new VecD(0, 0));
         Pressure = CreateOutput<double>("Pressure", "PRESSURE", 1.0);
         Pressure = CreateOutput<double>("Pressure", "PRESSURE", 1.0);
         Twist = CreateOutput<double>("Twist", "TWIST", 0.0);
         Twist = CreateOutput<double>("Twist", "TWIST", 0.0);
@@ -32,6 +36,8 @@ public class PointerInfoNode : Node
             return;
             return;
         }
         }
 
 
+        IsLeftButtonPressed.Value = context.PointerInfo.IsLeftButtonPressed;
+        IsRightButtonPressed.Value = context.PointerInfo.IsRightButtonPressed;
         PositionOnCanvas.Value = context.PointerInfo.PositionOnCanvas;
         PositionOnCanvas.Value = context.PointerInfo.PositionOnCanvas;
         Pressure.Value = context.PointerInfo.Pressure;
         Pressure.Value = context.PointerInfo.Pressure;
         Twist.Value = context.PointerInfo.Twist;
         Twist.Value = context.PointerInfo.Twist;

+ 5 - 1
src/PixiEditor.ChangeableDocument/Rendering/ContextData/PointerInfo.cs

@@ -4,6 +4,8 @@ namespace PixiEditor.ChangeableDocument.Rendering.ContextData;
 
 
 public record struct PointerInfo
 public record struct PointerInfo
 {
 {
+    public bool IsLeftButtonPressed { get; set; }
+    public bool IsRightButtonPressed { get; set; }
     public VecD PositionOnCanvas { get; set; }
     public VecD PositionOnCanvas { get; set; }
     public float Pressure { get; set; }
     public float Pressure { get; set; }
     public float Twist { get; set; }
     public float Twist { get; set; }
@@ -11,13 +13,15 @@ public record struct PointerInfo
     public VecD MovementDirection { get; set; }
     public VecD MovementDirection { get; set; }
     public double Rotation { get; set; }
     public double Rotation { get; set; }
 
 
-    public PointerInfo(VecD positionOnCanvas, float pressure, float twist, VecD tilt, VecD movementDirection)
+    public PointerInfo(VecD positionOnCanvas, float pressure, float twist, VecD tilt, VecD movementDirection, bool isLeftButtonPressed, bool isRightButtonPressed)
     {
     {
         PositionOnCanvas = positionOnCanvas;
         PositionOnCanvas = positionOnCanvas;
         Pressure = pressure;
         Pressure = pressure;
         Twist = twist;
         Twist = twist;
         Tilt = tilt;
         Tilt = tilt;
         MovementDirection = movementDirection;
         MovementDirection = movementDirection;
+        IsLeftButtonPressed = isLeftButtonPressed;
+        IsRightButtonPressed = isRightButtonPressed;
         Rotation = Math.Atan2(movementDirection.Y, movementDirection.X);
         Rotation = Math.Atan2(movementDirection.Y, movementDirection.X);
     }
     }
 }
 }

BIN
src/PixiEditor/Data/BrushTools/Brightness.pixi


+ 1 - 0
src/PixiEditor/Data/Configs/ToolSetsConfig.json

@@ -6,6 +6,7 @@
       "Icon": "icon-sun",
       "Icon": "icon-sun",
       "ToolTip": "BRIGHTNESS_TOOL_TOOLTIP",
       "ToolTip": "BRIGHTNESS_TOOL_TOOLTIP",
       "DefaultShortcut": "U",
       "DefaultShortcut": "U",
+      "SupportsSecondaryActionOnRightClick": true,
       "ActionDisplays": [
       "ActionDisplays": [
         {
         {
           "ActionDisplay": "BRIGHTNESS_TOOL_ACTION_DISPLAY_DEFAULT"
           "ActionDisplay": "BRIGHTNESS_TOOL_ACTION_DISPLAY_DEFAULT"

+ 3 - 0
src/PixiEditor/Models/Config/ToolsConfig.cs

@@ -43,6 +43,7 @@ public class ToolsConfig : IMergeable<ToolsConfig>
                         existingTool.DefaultShortcut = string.IsNullOrEmpty(tool.DefaultShortcut)
                         existingTool.DefaultShortcut = string.IsNullOrEmpty(tool.DefaultShortcut)
                             ? existingTool.DefaultShortcut
                             ? existingTool.DefaultShortcut
                             : tool.DefaultShortcut;
                             : tool.DefaultShortcut;
+                        existingTool.SupportsSecondaryActionOnRightClick = tool.SupportsSecondaryActionOnRightClick;
                         existingTool.ToolTip = string.IsNullOrEmpty(tool.ToolTip) ? existingTool.ToolTip : tool.ToolTip;
                         existingTool.ToolTip = string.IsNullOrEmpty(tool.ToolTip) ? existingTool.ToolTip : tool.ToolTip;
                         if (existingTool.Settings != null && tool.Settings != null)
                         if (existingTool.Settings != null && tool.Settings != null)
                         {
                         {
@@ -92,6 +93,7 @@ public class ToolsConfig : IMergeable<ToolsConfig>
                                     : tool.DefaultShortcut;
                                     : tool.DefaultShortcut;
                                 existingTool.ToolTip =
                                 existingTool.ToolTip =
                                     string.IsNullOrEmpty(tool.ToolTip) ? existingTool.ToolTip : tool.ToolTip;
                                     string.IsNullOrEmpty(tool.ToolTip) ? existingTool.ToolTip : tool.ToolTip;
+                                existingTool.SupportsSecondaryActionOnRightClick = tool.SupportsSecondaryActionOnRightClick;
 
 
                                 if (existingTool.Settings != null && tool.Settings != null)
                                 if (existingTool.Settings != null && tool.Settings != null)
                                 {
                                 {
@@ -151,6 +153,7 @@ public class ToolConfig
     public bool IsSimpleTool => Settings == null || Settings.Count == 0;
     public bool IsSimpleTool => Settings == null || Settings.Count == 0;
     public string? Icon { get; set; }
     public string? Icon { get; set; }
     public List<ActionDisplayConfig>? ActionDisplays { get; set; }
     public List<ActionDisplayConfig>? ActionDisplays { get; set; }
+    public bool SupportsSecondaryActionOnRightClick { get; set; }
 }
 }
 
 
 public class ActionDisplayConfig
 public class ActionDisplayConfig

+ 1 - 0
src/PixiEditor/Models/Controllers/InputDevice/MouseOnCanvasEventArgs.cs

@@ -15,6 +15,7 @@ internal class MouseOnCanvasEventArgs : EventArgs
     public int ClickCount { get; set; } = 1;
     public int ClickCount { get; set; } = 1;
     public double ViewportScale { get; set; }
     public double ViewportScale { get; set; }
     public IReadOnlyList<PointerPosition> IntermediatePoints { get; set; }
     public IReadOnlyList<PointerPosition> IntermediatePoints { get; set; }
+    public PointerPointProperties Properties => Point.Properties;
 
 
     public MouseOnCanvasEventArgs(MouseButton button, PointerType type, VecD positionOnCanvas, KeyModifiers keyModifiers, int clickCount,
     public MouseOnCanvasEventArgs(MouseButton button, PointerType type, VecD positionOnCanvas, KeyModifiers keyModifiers, int clickCount,
         PointerPointProperties properties, double viewportScale)
         PointerPointProperties properties, double viewportScale)

+ 18 - 1
src/PixiEditor/Models/DocumentModels/ChangeExecutionController.cs

@@ -21,6 +21,7 @@ namespace PixiEditor.Models.DocumentModels;
 internal class ChangeExecutionController
 internal class ChangeExecutionController
 {
 {
     public bool LeftMousePressed { get; private set; }
     public bool LeftMousePressed { get; private set; }
+    public bool RightMousePressed { get; private set; }
     public ShapeCorners LastTransformState { get; private set; }
     public ShapeCorners LastTransformState { get; private set; }
     public VecI LastPixelPosition => lastPixelPos;
     public VecI LastPixelPosition => lastPixelPos;
     public VecD LastPrecisePosition => lastPrecisePos;
     public VecD LastPrecisePosition => lastPrecisePos;
@@ -240,7 +241,9 @@ internal class ChangeExecutionController
     {
     {
         //update internal state
         //update internal state
         LeftMousePressed = true;
         LeftMousePressed = true;
+        RightMousePressed = args.Properties.IsRightButtonPressed;
 
 
+        lastPointerInfo = ConstructPointerInfo(args.Point.PositionOnCanvas, args);
         if (_queuedExecutor != null && currentSession == null)
         if (_queuedExecutor != null && currentSession == null)
         {
         {
             StartExecutor(_queuedExecutor);
             StartExecutor(_queuedExecutor);
@@ -258,6 +261,20 @@ internal class ChangeExecutionController
         //call session events
         //call session events
         currentSession?.OnLeftMouseButtonUp(argsPositionOnCanvas);
         currentSession?.OnLeftMouseButtonUp(argsPositionOnCanvas);
     }
     }
+    
+    public void RightMouseButtonDownInlet(MouseOnCanvasEventArgs args)
+    {
+        RightMousePressed = true;
+        LeftMousePressed = args.Properties.IsLeftButtonPressed;
+        lastPointerInfo = ConstructPointerInfo(args.Point.PositionOnCanvas, args);
+        currentSession?.OnRightMouseButtonDown(args);
+    }
+    
+    public void RightMouseButtonUpInlet(VecD argsPositionOnCanvas)
+    {
+        RightMousePressed = false;
+        currentSession?.OnRightMouseButtonUp(argsPositionOnCanvas);
+    }
 
 
     public void TransformChangedInlet(ShapeCorners corners)
     public void TransformChangedInlet(ShapeCorners corners)
     {
     {
@@ -388,6 +405,6 @@ internal class ChangeExecutionController
         }
         }
 
 
         return new PointerInfo(currentPoint, pressure, args.Point.Properties.Twist,
         return new PointerInfo(currentPoint, pressure, args.Point.Properties.Twist,
-            new VecD(args.Point.Properties.XTilt, args.Point.Properties.YTilt), dirNormalized);
+            new VecD(args.Point.Properties.XTilt, args.Point.Properties.YTilt), dirNormalized, LeftMousePressed, RightMousePressed);
     }
     }
 }
 }

+ 2 - 0
src/PixiEditor/Models/DocumentModels/Public/DocumentEventsModule.cs

@@ -42,6 +42,8 @@ internal class DocumentEventsModule
     }
     }
 
 
     public void OnCanvasLeftMouseButtonUp(VecD argsPositionOnCanvas) => Internals.ChangeController.LeftMouseButtonUpInlet(argsPositionOnCanvas);
     public void OnCanvasLeftMouseButtonUp(VecD argsPositionOnCanvas) => Internals.ChangeController.LeftMouseButtonUpInlet(argsPositionOnCanvas);
+    public void OnCanvasRightMouseButtonDown(MouseOnCanvasEventArgs args) => Internals.ChangeController.RightMouseButtonDownInlet(args);
+    public void OnCanvasRightMouseButtonUp(VecD argsPositionOnCanvas) => Internals.ChangeController.RightMouseButtonUpInlet(argsPositionOnCanvas);
     public void OnOpacitySliderDragStarted() => Internals.ChangeController.OpacitySliderDragStartedInlet();
     public void OnOpacitySliderDragStarted() => Internals.ChangeController.OpacitySliderDragStartedInlet();
     public void OnOpacitySliderDragged(float newValue) => Internals.ChangeController.OpacitySliderDraggedInlet(newValue);
     public void OnOpacitySliderDragged(float newValue) => Internals.ChangeController.OpacitySliderDraggedInlet(newValue);
     public void OnOpacitySliderDragEnded() => Internals.ChangeController.OpacitySliderDragEndedInlet();
     public void OnOpacitySliderDragEnded() => Internals.ChangeController.OpacitySliderDragEndedInlet();

+ 2 - 0
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/UpdateableChangeExecutor.cs

@@ -51,6 +51,8 @@ internal abstract class UpdateableChangeExecutor
     public virtual void OnPrecisePositionChange(MouseOnCanvasEventArgs args) { }
     public virtual void OnPrecisePositionChange(MouseOnCanvasEventArgs args) { }
     public virtual void OnLeftMouseButtonDown(MouseOnCanvasEventArgs args) { }
     public virtual void OnLeftMouseButtonDown(MouseOnCanvasEventArgs args) { }
     public virtual void OnLeftMouseButtonUp(VecD pos) { }
     public virtual void OnLeftMouseButtonUp(VecD pos) { }
+    public virtual void OnRightMouseButtonDown(MouseOnCanvasEventArgs args) { }
+    public virtual void OnRightMouseButtonUp(VecD pos) { }
     public virtual void OnOpacitySliderDragStarted() { }
     public virtual void OnOpacitySliderDragStarted() { }
     public virtual void OnOpacitySliderDragged(float newValue) { }
     public virtual void OnOpacitySliderDragged(float newValue) { }
     public virtual void OnOpacitySliderDragEnded() { }
     public virtual void OnOpacitySliderDragEnded() { }

+ 1 - 1
src/PixiEditor/ViewModels/Document/DocumentManagerViewModel.cs

@@ -47,7 +47,7 @@ internal class DocumentManagerViewModel : SubViewModel<ViewModelMain>, IDocument
             if (ViewModelMain.Current.ToolsSubViewModel.ActiveTool == null)
             if (ViewModelMain.Current.ToolsSubViewModel.ActiveTool == null)
             {
             {
                 var firstTool =
                 var firstTool =
-                    ViewModelMain.Current.ToolsSubViewModel.ActiveToolSet.Tools.FirstOrDefault(x =>
+                    ViewModelMain.Current.ToolsSubViewModel.ActiveToolSet?.Tools.FirstOrDefault(x =>
                         x.CanBeUsedOnActiveLayer);
                         x.CanBeUsedOnActiveLayer);
                 if (firstTool != null)
                 if (firstTool != null)
                 {
                 {

+ 16 - 6
src/PixiEditor/ViewModels/SubViewModels/IoViewModel.cs

@@ -247,14 +247,20 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
         if (drawingWithRight != null || args.Button is not (MouseButton.Left or MouseButton.Right))
         if (drawingWithRight != null || args.Button is not (MouseButton.Left or MouseButton.Right))
             return;
             return;
 
 
-        if (args.Button == MouseButton.Right && !HandleRightMouseDown())
-            return;
-
         var docManager = Owner.DocumentManagerSubViewModel;
         var docManager = Owner.DocumentManagerSubViewModel;
         var activeDocument = docManager.ActiveDocument;
         var activeDocument = docManager.ActiveDocument;
         if (activeDocument == null)
         if (activeDocument == null)
             return;
             return;
 
 
+        if (args.Button == MouseButton.Right)
+        {
+            activeDocument.EventInlet.OnCanvasRightMouseButtonDown(args);
+            if (!HandleRightMouseDown())
+            {
+                return;
+            }
+        }
+
         drawingWithRight = args.Button == MouseButton.Right;
         drawingWithRight = args.Button == MouseButton.Right;
         activeDocument.EventInlet.OnCanvasLeftMouseButtonDown(args);
         activeDocument.EventInlet.OnCanvasLeftMouseButtonDown(args);
         if (args.Handled) return;
         if (args.Handled) return;
@@ -296,10 +302,8 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
                 HandleRightMouseEraseDown(tools);
                 HandleRightMouseEraseDown(tools);
                 return true;
                 return true;
             }
             }
-            /*
-            case RightClickMode.SecondaryColor when tools.ActiveTool is BrightnessToolViewModel:
+            case RightClickMode.SecondaryColor when tools.ActiveTool is BrushBasedToolViewModel { SupportsSecondaryActionOnRightClick: true }:
                 return true;
                 return true;
-            */
             case RightClickMode.ContextMenu:
             case RightClickMode.ContextMenu:
             default:
             default:
                 return false;
                 return false;
@@ -397,6 +401,12 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
             Owner.DocumentManagerSubViewModel.ActiveDocument.EventInlet
             Owner.DocumentManagerSubViewModel.ActiveDocument.EventInlet
                 .OnCanvasLeftMouseButtonUp(args.Point.PositionOnCanvas);
                 .OnCanvasLeftMouseButtonUp(args.Point.PositionOnCanvas);
         }
         }
+        
+        if (button == MouseButton.Right)
+        {
+            Owner.DocumentManagerSubViewModel.ActiveDocument.EventInlet
+                .OnCanvasRightMouseButtonUp(args.Point.PositionOnCanvas);
+        }
 
 
         drawingWithRight = null;
         drawingWithRight = null;
 
 

+ 3 - 3
src/PixiEditor/ViewModels/SubViewModels/ToolsViewModel.cs

@@ -119,7 +119,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
         }
         }
     }
     }
 
 
-    public IToolSetHandler ActiveToolSet
+    public IToolSetHandler? ActiveToolSet
     {
     {
         get => _activeToolSet!;
         get => _activeToolSet!;
         private set => SetProperty(ref _activeToolSet, value);
         private set => SetProperty(ref _activeToolSet, value);
@@ -728,7 +728,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
                     var brush = new Brush(uri, "TOOL_CONFIG");
                     var brush = new Brush(uri, "TOOL_CONFIG");
                     KeyCombination? shortcut = TryParseShortcut(toolFromToolset.DefaultShortcut);
                     KeyCombination? shortcut = TryParseShortcut(toolFromToolset.DefaultShortcut);
                     return new BrushBasedToolViewModel(new BrushViewModel(brush), toolFromToolset.ToolTip, toolFromToolset.ToolName,
                     return new BrushBasedToolViewModel(new BrushViewModel(brush), toolFromToolset.ToolTip, toolFromToolset.ToolName,
-                        shortcut, toolFromToolset.ActionDisplays);
+                        shortcut, toolFromToolset.ActionDisplays, toolFromToolset.SupportsSecondaryActionOnRightClick);
                 }
                 }
             }
             }
             catch
             catch
@@ -800,7 +800,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
     private void UpdateEnabledState()
     private void UpdateEnabledState()
     {
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
-        if (doc is null)
+        if (doc is null || ActiveToolSet is null)
             return;
             return;
 
 
         foreach (var toolHandler in ActiveToolSet.Tools)
         foreach (var toolHandler in ActiveToolSet.Tools)

+ 5 - 1
src/PixiEditor/ViewModels/Tools/Tools/BrushBasedToolViewModel.cs

@@ -28,7 +28,10 @@ internal class BrushBasedToolViewModel : ToolViewModel, IBrushToolHandler
     public override string ToolNameLocalizationKey => toolName;
     public override string ToolNameLocalizationKey => toolName;
     public override string ToolName => toolName ?? base.ToolName;
     public override string ToolName => toolName ?? base.ToolName;
     public bool IsCustomBrushTool { get; private set; }
     public bool IsCustomBrushTool { get; private set; }
+    public override bool UsesColor => true;
+    public override bool IsErasable => true;
     public KeyCombination? DefaultShortcut { get; set; }
     public KeyCombination? DefaultShortcut { get; set; }
+    public bool SupportsSecondaryActionOnRightClick { get; set; }
 
 
     public VecD LastAppliedPoint
     public VecD LastAppliedPoint
     {
     {
@@ -52,7 +55,7 @@ internal class BrushBasedToolViewModel : ToolViewModel, IBrushToolHandler
     }
     }
 
 
     public BrushBasedToolViewModel(BrushViewModel brush, string? tooltip, string? toolName, KeyCombination? defaultShortcut,
     public BrushBasedToolViewModel(BrushViewModel brush, string? tooltip, string? toolName, KeyCombination? defaultShortcut,
-        List<ActionDisplayConfig>? actionDisplays)
+        List<ActionDisplayConfig>? actionDisplays, bool supportsSecondaryActionOnRightClick)
     {
     {
         Cursor = Cursors.PreciseCursor;
         Cursor = Cursors.PreciseCursor;
         Toolbar = CreateToolbar();
         Toolbar = CreateToolbar();
@@ -69,6 +72,7 @@ internal class BrushBasedToolViewModel : ToolViewModel, IBrushToolHandler
         DefaultShortcut = defaultShortcut;
         DefaultShortcut = defaultShortcut;
         IsCustomBrushTool = true;
         IsCustomBrushTool = true;
         this.actionDisplays = ParseActionDisplays(actionDisplays);
         this.actionDisplays = ParseActionDisplays(actionDisplays);
+        SupportsSecondaryActionOnRightClick = supportsSecondaryActionOnRightClick;
 
 
         if (this.actionDisplays is { Count: > 0 })
         if (this.actionDisplays is { Count: > 0 })
         {
         {

+ 16 - 9
src/PixiEditor/Views/Main/ViewportControls/Viewport.axaml.cs

@@ -5,6 +5,7 @@ using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls;
 using Avalonia.Input;
 using Avalonia.Input;
 using Avalonia.Interactivity;
 using Avalonia.Interactivity;
+using Avalonia.Media;
 using Avalonia.Skia;
 using Avalonia.Skia;
 using Avalonia.VisualTree;
 using Avalonia.VisualTree;
 using ChunkyImageLib;
 using ChunkyImageLib;
@@ -383,7 +384,8 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         set => SetValue(ViewportRenderOutputProperty, value);
         set => SetValue(ViewportRenderOutputProperty, value);
     }
     }
 
 
-    public static readonly StyledProperty<Func<EditorData>> EditorDataFuncProperty = AvaloniaProperty.Register<Viewport, Func<EditorData>>("EditorDataFunc");
+    public static readonly StyledProperty<Func<EditorData>> EditorDataFuncProperty =
+        AvaloniaProperty.Register<Viewport, Func<EditorData>>("EditorDataFunc");
 
 
     public ObservableCollection<Overlay> ActiveOverlays { get; } = new();
     public ObservableCollection<Overlay> ActiveOverlays { get; } = new();
 
 
@@ -534,7 +536,8 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
     private ViewportInfo GetLocation()
     private ViewportInfo GetLocation()
     {
     {
         return new(AngleRadians, Center, RealDimensions,
         return new(AngleRadians, Center, RealDimensions,
-            new ViewportData(Scene.CalculateTransformMatrix().ToSKMatrix().ToMatrix3X3(), Scene.Pan, Scene.Scale, FlipX, FlipY),
+            new ViewportData(Scene.CalculateTransformMatrix().ToSKMatrix().ToMatrix3X3(), Scene.Pan, Scene.Scale, FlipX,
+                FlipY),
             Scene.LastPointerInfo,
             Scene.LastPointerInfo,
             Scene.LastKeyboardInfo,
             Scene.LastKeyboardInfo,
             EditorDataFunc(),
             EditorDataFunc(),
@@ -576,7 +579,8 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         VecD conv = Scene.ToZoomboxSpace(new VecD(pos.X, pos.Y));
         VecD conv = Scene.ToZoomboxSpace(new VecD(pos.X, pos.Y));
         MouseButton mouseButton = e.GetMouseButton(this);
         MouseButton mouseButton = e.GetMouseButton(this);
 
 
-        MouseOnCanvasEventArgs parameter = new(mouseButton, e.Pointer.Type, conv, e.KeyModifiers, 0, e.GetCurrentPoint(this).Properties, Scene.Scale);
+        MouseOnCanvasEventArgs parameter = new(mouseButton, e.Pointer.Type, conv, e.KeyModifiers, 0,
+            e.GetCurrentPoint(this).Properties, Scene.Scale);
 
 
         var intermediate = e.GetIntermediatePoints(this);
         var intermediate = e.GetIntermediatePoints(this);
         List<PointerPosition> intermediatePositions = new();
         List<PointerPosition> intermediatePositions = new();
@@ -601,7 +605,8 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
 
 
         Point pos = e.GetPosition(Scene);
         Point pos = e.GetPosition(Scene);
         VecD conv = Scene.ToZoomboxSpace(new VecD(pos.X, pos.Y));
         VecD conv = Scene.ToZoomboxSpace(new VecD(pos.X, pos.Y));
-        MouseOnCanvasEventArgs parameter = new(e.InitialPressMouseButton, e.Pointer.Type, conv, e.KeyModifiers, 0, e.GetCurrentPoint(this).Properties, Scene.Scale);
+        MouseOnCanvasEventArgs parameter = new(e.InitialPressMouseButton, e.Pointer.Type, conv, e.KeyModifiers, 0,
+            e.GetCurrentPoint(this).Properties, Scene.Scale);
         if (MouseUpCommand.CanExecute(parameter))
         if (MouseUpCommand.CanExecute(parameter))
             MouseUpCommand.Execute(parameter);
             MouseUpCommand.Execute(parameter);
     }
     }
@@ -725,14 +730,16 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         ViewportWindowViewModel vm = ((ViewportWindowViewModel)DataContext);
         ViewportWindowViewModel vm = ((ViewportWindowViewModel)DataContext);
         var tools = vm.Owner.Owner.ToolsSubViewModel;
         var tools = vm.Owner.Owner.ToolsSubViewModel;
 
 
-        /*
-        var superSpecialBrightnessTool = tools.RightClickMode == RightClickMode.SecondaryColor &&
-                                         tools.ActiveTool is BrightnessToolViewModel;
-        */
+        var superSpecialRightClick = tools is { RightClickMode: RightClickMode.SecondaryColor, ActiveTool: BrushBasedToolViewModel
+            {
+                SupportsSecondaryActionOnRightClick: true
+            }
+        };
+
         var superSpecialColorPicker =
         var superSpecialColorPicker =
             tools.RightClickMode == RightClickMode.Erase && tools.ActiveTool is ColorPickerToolViewModel;
             tools.RightClickMode == RightClickMode.Erase && tools.ActiveTool is ColorPickerToolViewModel;
 
 
-        if (/*superSpecialBrightnessTool || */superSpecialColorPicker)
+        if (superSpecialRightClick || superSpecialColorPicker)
         {
         {
             return;
             return;
         }
         }

+ 1 - 1
src/PixiEditor/Views/Overlays/BrushShapeOverlay/BrushShapeOverlay.cs

@@ -183,7 +183,7 @@ internal class BrushShapeOverlay : Overlay
         VecD vecDir = new VecD(dir.X, dir.Y);
         VecD vecDir = new VecD(dir.X, dir.Y);
         VecD dirNormalized = vecDir.Length > 0 ? vecDir.Normalize() : lastPointerInfo.MovementDirection;
         VecD dirNormalized = vecDir.Length > 0 ? vecDir.Normalize() : lastPointerInfo.MovementDirection;
 
 
-        PointerInfo pointer = new PointerInfo(pos, 1, 0, VecD.Zero, dirNormalized);
+        PointerInfo pointer = new PointerInfo(pos, 1, 0, VecD.Zero, dirNormalized, true, false);
 
 
         engine.ExecuteBrush(null, BrushData, pos, ActiveFrameTime,
         engine.ExecuteBrush(null, BrushData, pos, ActiveFrameTime,
             ColorSpace.CreateSrgb(), SamplingOptions.Default, pointer, new KeyboardInfo(),
             ColorSpace.CreateSrgb(), SamplingOptions.Default, pointer, new KeyboardInfo(),

+ 1 - 1
src/PixiEditor/Views/Rendering/Scene.cs

@@ -819,7 +819,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         Point dir = lastDirCalculationPoint - data.Position;
         Point dir = lastDirCalculationPoint - data.Position;
         VecD vecDir = new VecD(dir.X, dir.Y);
         VecD vecDir = new VecD(dir.X, dir.Y);
         VecD dirNormalized = vecDir.Length > 0 ? vecDir.Normalize() : lastPointerInfo.MovementDirection;
         VecD dirNormalized = vecDir.Length > 0 ? vecDir.Normalize() : lastPointerInfo.MovementDirection;
-        return new PointerInfo(position, pressure, properties.Twist, new VecD(properties.XTilt, properties.YTilt), dirNormalized);
+        return new PointerInfo(position, pressure, properties.Twist, new VecD(properties.XTilt, properties.YTilt), dirNormalized, e.Properties.IsLeftButtonPressed, e.Properties.IsRightButtonPressed);
     }
     }
 
 
     private static Point Lerp(VecD a, VecD b, float t)
     private static Point Lerp(VecD a, VecD b, float t)