Kaynağa Gözat

Magic wand multi-layer support

Krzysztof Krysiński 2 yıl önce
ebeveyn
işleme
fa4e58f2d6

+ 10 - 11
src/PixiEditor.ChangeableDocument/Changes/Selection/MagicWand/MagicWand_Change.cs

@@ -10,18 +10,16 @@ internal class MagicWand_Change : Change
     private VectorPath? originalPath;
     private VectorPath path = new() { FillType = PathFillType.EvenOdd };
     private VecI point;
-    private readonly Guid memberGuid;
-    private readonly bool referenceAll;
+    private readonly List<Guid> memberGuids;
     private readonly bool drawOnMask;
     private readonly SelectionMode mode;
 
     [GenerateMakeChangeAction]
-    public MagicWand_Change(Guid memberGuid, VecI point, SelectionMode mode, bool referenceAll, bool drawOnMask)
+    public MagicWand_Change(List<Guid> memberGuids, VecI point, SelectionMode mode, bool drawOnMask)
     {
         path.MoveTo(point);
         this.mode = mode;
-        this.memberGuid = memberGuid;
-        this.referenceAll = referenceAll;
+        this.memberGuids = memberGuids;
         this.drawOnMask = drawOnMask;
         this.point = point;
     }
@@ -34,13 +32,14 @@ internal class MagicWand_Change : Change
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
-
         HashSet<Guid> membersToReference = new();
-        if (referenceAll)
-            target.ForEveryReadonlyMember(member => membersToReference.Add(member.GuidValue));
-        else
-            membersToReference.Add(memberGuid);
+
+        target.ForEveryReadonlyMember(member =>
+        {
+            if (memberGuids.Contains(member.GuidValue))
+                membersToReference.Add(member.GuidValue);
+        });
+
         path = MagicWandHelper.DoMagicWandFloodFill(point, membersToReference, target);
 
         ignoreInUndo = false;

+ 7 - 10
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/MagicWandToolExecutor.cs

@@ -11,28 +11,25 @@ internal class MagicWandToolExecutor : UpdateableChangeExecutor
 {
     private bool considerAllLayers;
     private bool drawOnMask;
-    private Guid memberGuid;
+    private List<Guid> memberGuids;
     private SelectionMode mode;
 
     public override ExecutionState Start()
     {
         var magicWand = ViewModelMain.Current?.ToolsSubViewModel.GetTool<MagicWandToolViewModel>();
-        var member = document!.SelectedStructureMember;
+        var members = document!.ExtractSelectedLayers(true);
 
-        if (magicWand is null || member is null)
-            return ExecutionState.Error;
-        drawOnMask = member is not LayerViewModel layer || layer.ShouldDrawOnMask;
-        if (drawOnMask && !member.HasMaskBindable)
-            return ExecutionState.Error;
-        if (!drawOnMask && member is not LayerViewModel)
+        if (magicWand is null || members.Count == 0)
             return ExecutionState.Error;
 
         mode = magicWand.SelectMode;
-        memberGuid = member.GuidValue;
+        memberGuids = members;
         considerAllLayers = magicWand.DocumentScope == DocumentScope.AllLayers;
+        if (considerAllLayers)
+            memberGuids = document!.StructureHelper.GetAllLayers().Select(x => x.GuidValue).ToList();
         var pos = controller!.LastPixelPosition;
 
-        internals!.ActionAccumulator.AddActions(new MagicWand_Action(memberGuid, pos, mode, considerAllLayers, drawOnMask));
+        internals!.ActionAccumulator.AddActions(new MagicWand_Action(memberGuids, pos, mode, considerAllLayers));
 
         return ExecutionState.Success;
     }

+ 48 - 2
src/PixiEditor/ViewModels/SubViewModels/Document/DocumentViewModel.cs

@@ -520,8 +520,54 @@ internal partial class DocumentViewModel : NotifyableObject
     /// </summary>
     public List<Guid> GetSelectedMembers()
     {
-        List<Guid> layerGuids = new List<Guid>() { SelectedStructureMember.GuidValue };
-        layerGuids.AddRange( SoftSelectedStructureMembers.Select(x => x.GuidValue));
+        List<Guid> layerGuids = new List<Guid>();
+        if (SelectedStructureMember is not null)
+            layerGuids.Add(SelectedStructureMember.GuidValue);
+
+        layerGuids.AddRange(SoftSelectedStructureMembers.Select(x => x.GuidValue));
         return layerGuids;
     }
+
+    public List<Guid> ExtractSelectedLayers(bool includeFoldersWithMask = false)
+    {
+        var result = new List<Guid>();
+        List<Guid> selectedMembers = GetSelectedMembers();
+        foreach (var member in selectedMembers)
+        {
+            var foundMember = StructureHelper.Find(member);
+            if (foundMember != null)
+            {
+                if (foundMember is LayerViewModel layer && selectedMembers.Contains(foundMember.GuidValue) && !result.Contains(layer.GuidValue))
+                {
+                    result.Add(layer.GuidValue);
+                }
+                else if (foundMember is FolderViewModel folder && selectedMembers.Contains(foundMember.GuidValue))
+                {
+                    if (includeFoldersWithMask && folder.HasMaskBindable && !result.Contains(folder.GuidValue))
+                        result.Add(folder.GuidValue);
+                    ExtractSelectedLayers(folder, result, includeFoldersWithMask);
+                }
+            }
+        }
+        return result;
+    }
+
+    private void ExtractSelectedLayers(FolderViewModel folder, List<Guid> list,
+        bool includeFoldersWithMask)
+    {
+        foreach (var member in folder.Children)
+        {
+            if (member is LayerViewModel layer && !list.Contains(layer.GuidValue))
+            {
+                list.Add(layer.GuidValue);
+            }
+            else if (member is FolderViewModel childFolder)
+            {
+                if (includeFoldersWithMask && childFolder.HasMaskBindable && !list.Contains(childFolder.GuidValue))
+                    list.Add(childFolder.GuidValue);
+
+                ExtractSelectedLayers(childFolder, list, includeFoldersWithMask);
+            }
+        }
+    }
 }