Browse Source

Precise cursor, fixed handles and disallow changing tool while drawing

Krzysztof Krysiński 1 year ago
parent
commit
bdf0c596e6

+ 17 - 4
src/PixiEditor.AvaloniaUI/Helpers/Converters/ImagePathToBitmapConverter.cs

@@ -1,4 +1,5 @@
 using System.Globalization;
 using System.Globalization;
+using System.IO;
 using System.Reflection;
 using System.Reflection;
 using Avalonia;
 using Avalonia;
 using Avalonia.Data;
 using Avalonia.Data;
@@ -13,11 +14,23 @@ internal class ImagePathToBitmapConverter : SingleInstanceConverter<ImagePathToB
     {
     {
         if (value is not string path)
         if (value is not string path)
             return AvaloniaProperty.UnsetValue;
             return AvaloniaProperty.UnsetValue;
-        
+
+        try
+        {
+            return LoadBitmapFromRelativePath(path);
+        }
+        catch (FileNotFoundException)
+        {
+            return AvaloniaProperty.UnsetValue;
+        }
+    }
+
+    public static Bitmap LoadBitmapFromRelativePath(string path)
+    {
         Uri uri = new($"avares://{Assembly.GetExecutingAssembly().FullName}{path}");
         Uri uri = new($"avares://{Assembly.GetExecutingAssembly().FullName}{path}");
         if (!AssetLoader.Exists(uri))
         if (!AssetLoader.Exists(uri))
-            return AvaloniaProperty.UnsetValue;
-        
-        return new Bitmap(AssetLoader.Open(uri));
+            throw new FileNotFoundException($"Could not find asset with path {path}");
+
+        return new Bitmap(AssetLoader.Open(uri)).CreateScaledBitmap(new PixelSize(32, 32));
     }
     }
 }
 }

BIN
src/PixiEditor.AvaloniaUI/Images/Tools/PreciseCursor.png


+ 13 - 0
src/PixiEditor.AvaloniaUI/Models/Input/Cursors.cs

@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Input;
+using Avalonia.Media.Imaging;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+
+namespace PixiEditor.AvaloniaUI.Models.Input;
+
+public static class Cursors
+{
+    public static Cursor PreciseCursor { get; } = new Cursor(
+        ImagePathToBitmapConverter.LoadBitmapFromRelativePath("/Images/Tools/PreciseCursor.png"),
+        new PixelPoint(16, 16));
+}

+ 1 - 0
src/PixiEditor.AvaloniaUI/ViewModels/Document/DocumentViewModel.cs

@@ -123,6 +123,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
     private readonly HashSet<StructureMemberViewModel> softSelectedStructureMembers = new();
     private readonly HashSet<StructureMemberViewModel> softSelectedStructureMembers = new();
 
 
     public bool UpdateableChangeActive => Internals.ChangeController.IsChangeActive;
     public bool UpdateableChangeActive => Internals.ChangeController.IsChangeActive;
+    public bool PointerDragChangeInProgress => Internals.ChangeController.IsChangeActive && Internals.ChangeController.LeftMousePressed;
     public bool HasSavedUndo => Internals.Tracker.HasSavedUndo;
     public bool HasSavedUndo => Internals.Tracker.HasSavedUndo;
     public bool HasSavedRedo => Internals.Tracker.HasSavedRedo;
     public bool HasSavedRedo => Internals.Tracker.HasSavedRedo;
 
 

+ 7 - 0
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ToolsViewModel.cs

@@ -1,8 +1,13 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Collections.ObjectModel;
+using System.IO;
 using System.Linq;
 using System.Linq;
+using System.Reflection;
+using Avalonia;
 using Avalonia.Input;
 using Avalonia.Input;
+using Avalonia.Media.Imaging;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Evaluators;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Evaluators;
 using PixiEditor.AvaloniaUI.Models.Controllers;
 using PixiEditor.AvaloniaUI.Models.Controllers;
@@ -136,6 +141,8 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
 
 
     public void SetActiveTool(IToolHandler tool, bool transient)
     public void SetActiveTool(IToolHandler tool, bool transient)
     {
     {
+        if(Owner.DocumentManagerSubViewModel.ActiveDocument is { PointerDragChangeInProgress: true }) return;
+
         if (ActiveTool == tool)
         if (ActiveTool == tool)
         {
         {
             ActiveTool.IsTransient = transient;
             ActiveTool.IsTransient = transient;

+ 3 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Tools/Tools/PenToolViewModel.cs

@@ -1,7 +1,9 @@
 using System.Linq;
 using System.Linq;
 using Avalonia.Input;
 using Avalonia.Input;
+using Avalonia.Media.Imaging;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands;
 using PixiEditor.AvaloniaUI.Models.Handlers.Tools;
 using PixiEditor.AvaloniaUI.Models.Handlers.Tools;
+using PixiEditor.AvaloniaUI.Models.Input;
 using PixiEditor.AvaloniaUI.ViewModels.Tools.ToolSettings.Settings;
 using PixiEditor.AvaloniaUI.ViewModels.Tools.ToolSettings.Settings;
 using PixiEditor.AvaloniaUI.ViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.AvaloniaUI.ViewModels.Tools.ToolSettings.Toolbars;
 using PixiEditor.AvaloniaUI.Views.Overlays.BrushShapeOverlay;
 using PixiEditor.AvaloniaUI.Views.Overlays.BrushShapeOverlay;
@@ -21,7 +23,7 @@ namespace PixiEditor.AvaloniaUI.ViewModels.Tools.Tools
 
 
         public PenToolViewModel()
         public PenToolViewModel()
         {
         {
-            Cursor = new Cursor(StandardCursorType.Help); // TODO: Create pen cursor
+            Cursor = Cursors.PreciseCursor;
             Toolbar = ToolbarFactory.Create<PenToolViewModel, BasicToolbar>(this);
             Toolbar = ToolbarFactory.Create<PenToolViewModel, BasicToolbar>(this);
             
             
             ViewModelMain.Current.ToolsSubViewModel.SelectedToolChanged += SelectedToolChanged;
             ViewModelMain.Current.ToolsSubViewModel.SelectedToolChanged += SelectedToolChanged;

+ 1 - 2
src/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml.cs

@@ -311,8 +311,7 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
 
 
         //TODO: It's weird that I had to do it this way, right click didn't raise Image_MouseUp otherwise.
         //TODO: It's weird that I had to do it this way, right click didn't raise Image_MouseUp otherwise.
         viewportGrid.AddHandler(PointerReleasedEvent, Image_MouseUp, RoutingStrategies.Tunnel);
         viewportGrid.AddHandler(PointerReleasedEvent, Image_MouseUp, RoutingStrategies.Tunnel);
-        // Below it's actually not weird, because order of events is wrong if used with bubble. Middle mouse drag for example doesn't work.
-        viewportGrid.AddHandler(PointerPressedEvent, Image_MouseDown, RoutingStrategies.Tunnel);
+        viewportGrid.AddHandler(PointerPressedEvent, Image_MouseDown, RoutingStrategies.Bubble);
 
 
         mouseUpdateController = new MouseUpdateController(this, Image_MouseMove);
         mouseUpdateController = new MouseUpdateController(this, Image_MouseMove);
     }
     }

+ 1 - 0
src/PixiEditor.AvaloniaUI/Views/Overlays/TransformOverlay/TransformOverlay.cs

@@ -362,6 +362,7 @@ internal class TransformOverlay : Overlay
         }
         }
         
         
         e.Pointer.Capture(this);
         e.Pointer.Capture(this);
+        e.Handled = true;
     }
     }
 
 
     protected override void OnPointerMoved(PointerEventArgs e)
     protected override void OnPointerMoved(PointerEventArgs e)

+ 9 - 3
src/PixiEditor.Zoombox/Zoombox.axaml.cs

@@ -176,9 +176,15 @@ public partial class Zoombox : UserControl, INotifyPropertyChanged
     private static void ZoomModeChanged(AvaloniaPropertyChangedEventArgs<ZoomboxMode> e)
     private static void ZoomModeChanged(AvaloniaPropertyChangedEventArgs<ZoomboxMode> e)
     {
     {
         Zoombox sender = (Zoombox)e.Sender;
         Zoombox sender = (Zoombox)e.Sender;
-        sender.activeDragOperation?.Terminate();
-        sender.activeDragOperation = null;
-        sender.activeMouseDownEventArgs = null;
+
+        bool reset = sender.activeDragOperation != null;
+
+        if (reset)
+        {
+            sender.activeDragOperation?.Terminate();
+            sender.activeDragOperation = null;
+            sender.activeMouseDownEventArgs = null;
+        }
     }
     }
 
 
     private double[]? zoomValues;
     private double[]? zoomValues;