Browse Source

Fixed create layer if needed

Krzysztof Krysiński 5 ngày trước cách đây
mục cha
commit
e48cd6e32f

+ 6 - 0
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -248,6 +248,12 @@ internal class DocumentOperationsModule : IDocumentOperations
         return Internals.StructureHelper.CreateNewStructureMember(structureMemberType, name, source);
     }
 
+    public Guid? ForceCreateStructureMember(Type structureMemberType, ActionSource source, string? name = null)
+    {
+        Internals.ChangeController.TryStopActiveExecutor();
+        return Internals.StructureHelper.CreateNewStructureMember(structureMemberType, name, source);
+    }
+
     /// <summary>
     /// Duplicates the member with the <paramref name="guidValue"/>
     /// </summary>

+ 3 - 0
src/PixiEditor/Models/Handlers/IToolsHandler.cs

@@ -38,4 +38,7 @@ internal interface IToolsHandler : IHandler
     public void OnPreUndoInlet();
     public void QuickToolSwitchInlet();
     public void ChangeToolSize(double by);
+    public bool CreateLayerIfNeeded();
+    public bool NeedsNewLayerForActiveTool();
+    public void DeselectActiveTool();
 }

+ 19 - 1
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -231,6 +231,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
 
     private bool isDisposed = false;
     private Guid referenceId = Guid.Empty;
+    private Queue<Action> queuedLayerReadyToUseActions = new();
 
     private DocumentViewModel()
     {
@@ -1096,7 +1097,19 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
 
 // these are intended to only be called from DocumentUpdater
 
-    public void InternalRaiseLayersChanged(LayersChangedEventArgs args) => LayersChanged?.Invoke(this, args);
+    public void InternalRaiseLayersChanged(LayersChangedEventArgs args)
+    {
+        LayersChanged?.Invoke(this, args);
+        if (queuedLayerReadyToUseActions.Count > 0)
+        {
+            foreach (var action in queuedLayerReadyToUseActions)
+            {
+                action();
+            }
+
+            queuedLayerReadyToUseActions.Clear();
+        }
+    }
 
     public void RaiseSizeChanged(DocumentSizeChangedEventArgs args) => SizeChanged?.Invoke(this, args);
 
@@ -1486,4 +1499,9 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
             nodeVm.UpdateLinkedStatus();
         }
     }
+
+    public void SubscribeLayerReadyToUseOnce(Action action)
+    {
+        queuedLayerReadyToUseActions.Enqueue(action);
+    }
 }

+ 26 - 5
src/PixiEditor/ViewModels/SubViewModels/IoViewModel.cs

@@ -69,7 +69,7 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
 
         keyboardFilter.OnConvertedKeyDown += OnConvertedKeyDown;
         keyboardFilter.OnConvertedKeyUp += OnConvertedKeyUp;
-        
+
         Owner.AttachedToWindow += AttachWindowEvents;
     }
 
@@ -262,17 +262,35 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
         }
 
         drawingWithRight = args.Button == MouseButton.Right;
+
+
         activeDocument.EventInlet.OnCanvasLeftMouseButtonDown(args);
         if (args.Handled) return;
 
-        Owner.ToolsSubViewModel.UseToolEventInlet(args.Point.PositionOnCanvas, args.Button);
+        if (Owner.ToolsSubViewModel.NeedsNewLayerForActiveTool())
+        {
+            var activeToolType = Owner.ToolsSubViewModel.ActiveTool.GetType();
+            Owner.DocumentManagerSubViewModel.ActiveDocument.Tools.TryStopActiveTool();
+            Owner.ToolsSubViewModel.CreateLayerIfNeeded();
+            Owner.ToolsSubViewModel.DeselectActiveTool();
+            Owner.DocumentManagerSubViewModel.ActiveDocument.SubscribeLayerReadyToUseOnce(() =>
+            {
+                Owner.ToolsSubViewModel.SetActiveTool(activeToolType, false);
+                Owner.ToolsSubViewModel.UseToolEventInlet(args.Point.PositionOnCanvas, args.Button);
+            });
+        }
+        else
+        {
+            Owner.ToolsSubViewModel.UseToolEventInlet(args.Point.PositionOnCanvas, args.Button);
+        }
 
         if (args.Button == MouseButton.Right)
         {
             HandleRightSwapColor();
         }
 
-        Analytics.SendUseTool(Owner.ToolsSubViewModel.ActiveTool, args.Point.PositionOnCanvas, activeDocument.SizeBindable);
+        Analytics.SendUseTool(Owner.ToolsSubViewModel.ActiveTool, args.Point.PositionOnCanvas,
+            activeDocument.SizeBindable);
     }
 
     private bool HandleRightMouseDown()
@@ -302,7 +320,10 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
                 HandleRightMouseEraseDown(tools);
                 return true;
             }
-            case RightClickMode.SecondaryColor when tools.ActiveTool is BrushBasedToolViewModel { SupportsSecondaryActionOnRightClick: true }:
+            case RightClickMode.SecondaryColor when tools.ActiveTool is BrushBasedToolViewModel
+            {
+                SupportsSecondaryActionOnRightClick: true
+            }:
                 return true;
             case RightClickMode.ContextMenu:
             default:
@@ -401,7 +422,7 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
             Owner.DocumentManagerSubViewModel.ActiveDocument.EventInlet
                 .OnCanvasLeftMouseButtonUp(args.Point.PositionOnCanvas);
         }
-        
+
         if (button == MouseButton.Right)
         {
             Owner.DocumentManagerSubViewModel.ActiveDocument.EventInlet

+ 8 - 0
src/PixiEditor/ViewModels/SubViewModels/LayersViewModel.cs

@@ -171,6 +171,14 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
         return doc.Operations.CreateStructureMember(layerType, source, name);
     }
 
+    public Guid? ForceNewLayer(Type layerType, ActionSource source, string? name = null)
+    {
+        if (Owner.DocumentManagerSubViewModel.ActiveDocument is not { } doc)
+            return null;
+
+        return doc.Operations.ForceCreateStructureMember(layerType, source, name);
+    }
+
     [Evaluator.CanExecute("PixiEditor.Layer.CanCreateNewMember")]
     public bool CanCreateNewMember()
     {

+ 58 - 31
src/PixiEditor/ViewModels/SubViewModels/ToolsViewModel.cs

@@ -26,6 +26,7 @@ using PixiEditor.Helpers;
 using PixiEditor.Helpers.UI;
 using PixiEditor.Models.BrushEngine;
 using PixiEditor.Models.Commands;
+using PixiEditor.Models.DocumentModels.Public;
 using PixiEditor.Models.Handlers.Toolbars;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Models.Input;
@@ -382,11 +383,13 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
         LastActionTool = ActiveTool;
         ActiveTool = tool;
 
-        ActiveTool.Toolbar.SettingChanged += ToolbarSettingChanged;
-
-        if (shareToolbar)
+        if (ActiveTool != null)
         {
-            ActiveTool.Toolbar.LoadSharedSettings();
+            ActiveTool.Toolbar.SettingChanged += ToolbarSettingChanged;
+            if (shareToolbar)
+            {
+                ActiveTool.Toolbar.LoadSharedSettings();
+            }
         }
 
         if (LastActionTool != ActiveTool)
@@ -394,15 +397,19 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
             SelectedToolChanged?.Invoke(this, new SelectedToolEventArgs(LastActionTool, ActiveTool));
         }
 
-        //update old tool
+
         LastActionTool?.KeyChanged(false, false, false, Key.None);
-        //update new tool
-        ActiveTool.KeyChanged(ctrlIsDown, shiftIsDown, altIsDown, lastKey);
-        ActiveTool.OnToolSelected(wasTransient);
 
-        tool.IsActive = true;
-        ActiveTool.IsTransient = transient;
-        SetToolCursor(tool.GetType());
+        ActiveTool?.KeyChanged(ctrlIsDown, shiftIsDown, altIsDown, lastKey);
+        ActiveTool?.OnToolSelected(wasTransient);
+
+        if (ActiveTool != null)
+        {
+            tool.IsActive = true;
+            ActiveTool.IsTransient = transient;
+            SetToolCursor(tool.GetType());
+        }
+
 
         if (Owner.StylusSubViewModel != null)
         {
@@ -448,6 +455,41 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
             toolbar.ToolSize = newSize;
     }
 
+    public bool CreateLayerIfNeeded()
+    {
+        bool created = false;
+        if (NeedsNewLayerForActiveTool())
+        {
+            using var changeBlock = Owner.DocumentManagerSubViewModel.ActiveDocument.Operations.StartChangeBlock();
+            Guid? createdLayer = Owner.LayersSubViewModel.NewLayer(
+                ActiveTool.LayerTypeToCreateOnEmptyUse,
+                ActionSource.Automated,
+                ActiveTool.DefaultNewLayerName);
+            if (createdLayer is not null)
+            {
+                Owner.DocumentManagerSubViewModel.ActiveDocument.Operations.SetSelectedMember(createdLayer.Value);
+            }
+
+            changeBlock.ExecuteQueuedActions();
+            created = true;
+        }
+
+        return created;
+    }
+
+    public bool NeedsNewLayerForActiveTool()
+    {
+        return ActiveTool is not { CanBeUsedOnActiveLayer: true } && ActiveTool?.LayerTypeToCreateOnEmptyUse != null;
+    }
+
+    public void DeselectActiveTool()
+    {
+        if (ActiveTool != null)
+        {
+            SetActiveTool((IToolHandler)null, false, null);
+        }
+    }
+
     [Evaluator.CanExecute("PixiEditor.Tools.CanChangeToolSize",
         nameof(ActiveTool))]
     public bool CanChangeToolSize() => Owner.ToolsSubViewModel.ActiveTool?.Toolbar is IToolSizeToolbar
@@ -574,31 +616,15 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
 
     public void UseToolEventInlet(VecD canvasPos, MouseButton button)
     {
+        if (ActiveTool is null)
+            return;
+
         ActiveTool.UsedWith = button;
         if (ActiveTool.StopsLinkedToolOnUse)
         {
             ViewModelMain.Current.DocumentManagerSubViewModel.ActiveDocument?.Operations.TryStopToolLinkedExecutor();
         }
 
-        bool waitForChange = false;
-
-        if (ActiveTool is not { CanBeUsedOnActiveLayer: true })
-        {
-            if (ActiveTool.LayerTypeToCreateOnEmptyUse == null) return;
-
-            using var changeBlock = Owner.DocumentManagerSubViewModel.ActiveDocument.Operations.StartChangeBlock();
-            Guid? createdLayer = Owner.LayersSubViewModel.NewLayer(
-                ActiveTool.LayerTypeToCreateOnEmptyUse,
-                ActionSource.Automated,
-                ActiveTool.DefaultNewLayerName);
-            if (createdLayer is not null)
-            {
-                Owner.DocumentManagerSubViewModel.ActiveDocument.Operations.SetSelectedMember(createdLayer.Value);
-            }
-
-            changeBlock.ExecuteQueuedActions();
-        }
-
         ActiveTool.UseTool(canvasPos);
     }
 
@@ -727,7 +753,8 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
                 {
                     var brush = new Brush(uri, "TOOL_CONFIG");
                     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, toolFromToolset.SupportsSecondaryActionOnRightClick);
                 }
             }